效果图

Android 自定义控件 按钮滚动选择_第1张图片

代码实现

package com.demo.ui.view;import android.annotation.TargetApi;import android.content.Context;import android.os.Build;import android.os.Handler;import android.support.v4.content.ContextCompat;import android.view.Gravity;import android.view.MotionEvent;import android.view.View;import android.widget.ImageView;import android.widget.LinearLayout;import android.widget.RelativeLayout;import android.widget.TextView;import com.demo.R;import com.demo.factory.Axis;import com.demo.utils.LogUtils;import java.util.ArrayList;import java.util.List;public class AirTemperatureView extends RelativeLayout{    private Context context;    private TextView tv;    private TextView tv_middle;   // private TextView tv_middle_small;    private  RelativeLayout Auto_layout;    private StringScrollPicker stringScrollPicker;    private List newList;    private ImageView img;    private ImageView img_left;    private ImageView img_right;    private int mPosition;    private Handler handler = new Handler();    /**     * 延迟线程,看是否还有下一个字符输入     */    private Runnable delayRun = new Runnable() {        @Override        public void run() {            stringScrollPicker.setVisibility(INVISIBLE);            img.setBackgroundResource(R.drawable.air_temp_bg);            tv_middle.setText(newList.get(mPosition));            //tv.setText("电池剩余"+newList.get(mPosition)+"%提醒你");            tv_middle.setVisibility(VISIBLE);            img_right.setVisibility(VISIBLE);            img_left.setVisibility(VISIBLE);            if(mListener != null) {                mListener.setAirTemper(mPosition+18);            }            LogUtils.e("空调刷新===","温度");        }    };    public AirTemperatureView(Context context){        super(context);        this.context = context;        init();    }    @TargetApi(Build.VERSION_CODES.M)    public void init(){        super.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, Axis.scaleX(230)));        LinearLayout parent = new LinearLayout(context);        parent.setOrientation(LinearLayout.VERTICAL);        LayoutParams parent_Params = new LayoutParams(LayoutParams.MATCH_PARENT, Axis.scaleX(230));        super.addView(parent,parent_Params);        RelativeLayout tv_layout = new RelativeLayout(context);        LinearLayout.LayoutParams tv_layout_Params = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, Axis.scaleX(50));        parent.addView(tv_layout,tv_layout_Params);        tv = new TextView(context);        tv.setText("温度");        tv.setTextSize(Axis.scaleTextSize(36));        tv.setTextColor(ContextCompat.getColor(context, R.color.white_70_color));//        LayoutParams tv_Params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);        tv_Params.addRule(RelativeLayout.CENTER_IN_PARENT);        tv_layout.addView(tv,tv_Params);        /**         * 滑动选择器         */        Auto_layout = new RelativeLayout(context);        LinearLayout.LayoutParams Auto_layout_Params = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, Axis.scaleX(150));        Auto_layout_Params.setMargins(0,Axis.scaleX(30),0,0);        parent.addView(Auto_layout,Auto_layout_Params);        img = new ImageView(context);        img.setId(R.id.EleRemindImage);        img.setBackgroundResource(R.drawable.air_temp_bg);        LayoutParams img_Params = new LayoutParams(Axis.scaleX(150), Axis.scaleX(150));        img_Params.addRule(RelativeLayout.CENTER_IN_PARENT);        Auto_layout.addView(img,img_Params);        img_left = new ImageView(context);        img_left.setBackgroundResource(R.drawable.battery_point);        LayoutParams img_left_Params = new LayoutParams(Axis.scaleX(14), Axis.scaleX(14));        img_left_Params.addRule(RelativeLayout.CENTER_VERTICAL);        img_left_Params.addRule(RelativeLayout.LEFT_OF,R.id.EleRemindImage);        img_left_Params.setMargins(0,0,Axis.scaleX(134),0);        Auto_layout.addView(img_left,img_left_Params);        img_right = new ImageView(context);        img_right.setBackgroundResource(R.drawable.battery_point);        LayoutParams img_right_Params = new LayoutParams(Axis.scaleX(14), Axis.scaleX(14));        img_right_Params.addRule(RelativeLayout.CENTER_VERTICAL);        img_right_Params.addRule(RelativeLayout.RIGHT_OF,R.id.EleRemindImage);        img_right_Params.setMargins(Axis.scaleX(134),0,0,0);        Auto_layout.addView(img_right,img_right_Params);        tv_middle = new TextView(context);        tv_middle.setTextSize(Axis.scaleTextSize(64));        tv_middle.setGravity(Gravity.CENTER);        tv_middle.setTextColor(0xFFFFFFFF);        LayoutParams tv_middle_Params = new LayoutParams(Axis.scaleX(150), Axis.scaleX(150));        tv_middle_Params.addRule(RelativeLayout.CENTER_IN_PARENT);        Auto_layout.addView(tv_middle,tv_middle_Params);        newList = new ArrayList<>();        newList.add("18");        newList.add("19");        newList.add("20");        newList.add("21");        newList.add("22");        newList.add("23");        newList.add("24");        newList.add("25");        newList.add("26");        newList.add("27");        newList.add("28");        newList.add("29");        newList.add("30");        newList.add("31");        newList.add("32");        tv_middle.setText(newList.get(0));        stringScrollPicker = new StringScrollPicker(context);        stringScrollPicker.setHorizontal(true);        stringScrollPicker.setVisibleItemCount(5);//可见5个  第3个  (3-1)个位中间        stringScrollPicker.setCenterPosition(2);        stringScrollPicker.setIsCirculation(true);        stringScrollPicker.setCanTap(true);        stringScrollPicker.setDisallowInterceptTouch(true);        LayoutParams stringScrollPicker_Params = new LayoutParams(LayoutParams.MATCH_PARENT,Axis.scaleX(150));        Auto_layout.addView(stringScrollPicker,stringScrollPicker_Params);        stringScrollPicker.setData(newList);        stringScrollPicker.setOnSelectedListener(new ScrollPickerView.OnSelectedListener() {            @Override            public void onSelected(ScrollPickerView scrollPickerView, final int position) {                mPosition = position;                handler.postDelayed(delayRun, 1500);            }        });        stringScrollPicker.setOnSelectedListener(new StringScrollPicker.OnDataSelectedListener() {            @Override            public void DataSelected(CharSequence data) {                //tv.setText("电池剩余"+data+"%提醒你");            }        });        stringScrollPicker.setSelectedPosition(0,false);//中间Item位置        stringScrollPicker.setVisibility(INVISIBLE);        stringScrollPicker.setOnTouchListener(new OnTouchListener() {            @Override            public boolean onTouch(View v, MotionEvent event) {                switch (event.getAction()){                    case MotionEvent.ACTION_DOWN:                        img.setBackgroundResource(R.drawable.battery_btn_p);                        if(delayRun!=null){                            handler.removeCallbacks(delayRun);                        }                        break;                }                return false;            }        });        img.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                stringScrollPicker.setVisibility(VISIBLE);                tv_middle.setVisibility(INVISIBLE);                img_right.setVisibility(INVISIBLE);                img_left.setVisibility(INVISIBLE);                img.setBackgroundResource(R.drawable.battery_btn_p);            }        });    }    /**     * 风速设置     * @param mPosition     */    public  void  setAirTemperature(int mPosition){        /**         * 在设置的时候不刷新         */        if(stringScrollPicker.getVisibility() == INVISIBLE){            if(mPosition > 32){                mPosition = 32;            }            stringScrollPicker.setSelectedPosition(mPosition-18,false);            tv_middle.setText(newList.get(mPosition-18));        }    }    public TemperatureListener mListener;    public void setOnTemperatureListener (TemperatureListener listener) {        mListener = listener;    }    public interface TemperatureListener {        void setAirTemper(int temperature);    }}

StringScrollPicker 类

package com.demo.ui.view;import android.annotation.TargetApi;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.os.Build;import android.support.annotation.RequiresApi;import android.text.Layout;import android.text.StaticLayout;import android.text.TextPaint;import android.util.AttributeSet;import android.util.Log;import com.demo.factory.Axis;import com.demo.utils.ColorUtil;import java.util.ArrayList;import java.util.Arrays;import java.util.List;public class StringScrollPicker extends ScrollPickerView {    private int mMeasureWidth;    private int mMeasureHeight;    private TextPaint mPaint; //    private int mMinTextSize = Axis.scaleX(64); // 最小的字体    private int mMaxTextSize = Axis.scaleX(64); // 最大的字体    // 字体渐变颜色    private int mStartColor = Color.WHITE; // 中间选中item的颜色    private int mEndColor = Color.GRAY; // 上下两边的颜色    private int mMaxLineWidth = -1; // 最大的行宽,默认为itemWidth.超过后文字自动换行    private Layout.Alignment mAlignment = Layout.Alignment.ALIGN_CENTER; // 对齐方式,默认居中    @TargetApi(Build.VERSION_CODES.CUPCAKE)    public StringScrollPicker(Context context) {        this(context, null);    }    @RequiresApi(api = Build.VERSION_CODES.CUPCAKE)    public StringScrollPicker(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    @RequiresApi(api = Build.VERSION_CODES.CUPCAKE)    public StringScrollPicker(Context context, AttributeSet attrs,                              int defStyleAttr) {        super(context, attrs, defStyleAttr);        mPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);        mPaint.setStyle(Paint.Style.FILL);        mPaint.setColor(Color.BLACK);        setData(new ArrayList(Arrays.asList(new String[]{                "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve"        })));    }    /**     * @param startColor 正中间的颜色     * @param endColor   上下两边的颜色     */    public void setColor(int startColor, int endColor) {        mStartColor = startColor;        mEndColor = endColor;        invalidate();    }    /**     * item文字大小     *     * @param minText 沒有被选中时的最小文字     * @param maxText 被选中时的最大文字     */    public void setTextSize(int minText, int maxText) {        mMinTextSize = minText;        mMaxTextSize = maxText;        invalidate();    }    public int getStartColor() {        return mStartColor;    }    public int getEndColor() {        return mEndColor;    }    public int getMinTextSize() {        return mMinTextSize;    }    public int getMaxTextSize() {        return mMaxTextSize;    }    public int getMaxLineWidth() {        return mMaxLineWidth;    }    /**     * 最大的行宽,默认为itemWidth.超过后文字自动换行     * @param maxLineWidth     */    public void setMaxLineWidth(int maxLineWidth) {        mMaxLineWidth = maxLineWidth;    }    /**     * 最大的行宽,默认为itemWidth.超过后文字自动换行     * @return     */    public Layout.Alignment getAlignment() {        return mAlignment;    }    public void setAlignment(Layout.Alignment alignment) {        mAlignment = alignment;    }    @Override    protected void onSizeChanged(int w, int h, int oldw, int oldh) {        super.onSizeChanged(w, h, oldw, oldh);        mMeasureWidth = getMeasuredWidth();        mMeasureHeight = getMeasuredHeight();        if (mMaxLineWidth < 0) {            mMaxLineWidth = getItemWidth();        }    }    @Override    public void drawItem(Canvas canvas, List data, int position, int relative, float moveLength, float top) {        CharSequence text = data.get(position);        int itemSize = getItemSize();        // 设置文字大小        if (relative == -1) { // 上一个            if (moveLength < 0) { // 向上滑动                mPaint.setTextSize(mMinTextSize);            } else { // 向下滑动                mPaint.setTextSize(mMinTextSize + (mMaxTextSize - mMinTextSize)                        * moveLength / itemSize);            }        } else if (relative == 0) { // 中间item,当前选中            mPaint.setTextSize(mMinTextSize + (mMaxTextSize - mMinTextSize)                    * (itemSize - Math.abs(moveLength)) / itemSize);        } else if (relative == 1) { // 下一个            if (moveLength > 0) { // 向下滑动                mPaint.setTextSize(mMinTextSize);            } else { // 向上滑动                mPaint.setTextSize(mMinTextSize + (mMaxTextSize - mMinTextSize)                        * -moveLength / itemSize);            }        } else { // 其他            mPaint.setTextSize(mMinTextSize);        }        StaticLayout layout = new StaticLayout(text, 0, text.length(), mPaint, mMaxLineWidth, mAlignment, 1.0F, 0.0F, true, null, 0);        float x = 0;        float y = 0;        float lineWidth = layout.getWidth();        if (isHorizontal()) { // 水平滚动            x = top + (getItemWidth() - lineWidth) / 2;            y = (getItemHeight() - layout.getHeight()) / 2;        } else { // 垂直滚动            x = (getItemWidth() - lineWidth) / 2;            y = top + (getItemHeight() - layout.getHeight()) / 2;        }        // 计算渐变颜色        computeColor(relative, itemSize, moveLength,text);//        canvas.drawText(text, x, y, mPaint);        canvas.save();        canvas.translate(x, y);        layout.draw(canvas);        canvas.restore();    }    /**     * 计算字体颜色,渐变     *     * @param relative  相对中间item的位置     */    private String lastString;    private String nowSring;    private void computeColor(int relative, int itemSize, float moveLength, CharSequence text) {        int color = mEndColor; //  其他默认为mEndColor        if (relative == -1 || relative == 1) { // 上一个或下一个            // 处理上一个item且向上滑动 或者 处理下一个item且向下滑动 ,颜色为mEndColor            if ((relative == -1 && moveLength < 0)                    || (relative == 1 && moveLength > 0)) {                color = mEndColor;            } else { // 计算渐变的颜色                float rate = (itemSize - Math.abs(moveLength))                        / itemSize;                color = ColorUtil.computeGradientColor(mStartColor, mEndColor, rate);            }        } else if (relative == 0) { // 中间item            float rate = Math.abs(moveLength) / itemSize;            color = ColorUtil.computeGradientColor(mStartColor, mEndColor, rate);            nowSring = text.toString();            if(nowSring != lastString){                Log.e("text=====",text+"");                if(mListener != null){                    mListener.DataSelected(text);                }            }            lastString = nowSring;        }        mPaint.setColor(color);    }    public interface OnDataSelectedListener {        void DataSelected(CharSequence data);    }    public void setOnSelectedListener(OnDataSelectedListener listener) {        mListener = listener;    }    public  OnDataSelectedListener mListener;}

ScrollPickerView 类

package com.demo.ui.view;import android.animation.Animator;import android.animation.AnimatorListenerAdapter;import android.animation.ValueAnimator;import android.annotation.TargetApi;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.drawable.ColorDrawable;import android.graphics.drawable.Drawable;import android.os.Build;import android.support.annotation.RequiresApi;import android.util.AttributeSet;import android.util.DisplayMetrics;import android.view.GestureDetector;import android.view.MotionEvent;import android.view.View;import android.view.ViewParent;import android.view.animation.Interpolator;import android.widget.Scroller;import com.demo.R;import com.demo.utils.LogUtils;import java.util.ArrayList;import java.util.List;/** * 滚动选择器,带惯性滑动 */public abstract class ScrollPickerView extends View {    private int mVisibleItemCount = 3; // 可见的item数量    private boolean mIsInertiaScroll = true; // 快速滑动时是否惯性滚动一段距离,默认开启    private boolean mIsCirculation = true; // 是否循环滚动,默认开启    /*      不允许父组件拦截触摸事件,设置为true为不允许拦截,此时该设置才生效      当嵌入到ScrollView等滚动组件中,为了使该自定义滚动选择器可以正常工作,请设置为true     */    private boolean mDisallowInterceptTouch = false;    private int mSelected; // 当前选中的item下标    private int mLastSelected; // 当前选中的item下标    private List mData;    private int mItemHeight = 0; // 每个条目的高度,当垂直滚动时,高度=mMeasureHeight/mVisibleItemCount    private int mItemWidth = 0; // 每个条目的宽度,当水平滚动时,宽度=mMeasureWidth/mVisibleItemCount    private int mItemSize; // 当垂直滚动时,mItemSize = mItemHeight;水平滚动时,mItemSize = mItemWidth    private int mCenterPosition = -1; // 中间item的位置,0<=mCenterPosition<mVisibleItemCount,默认为 mVisibleItemCount / 2    private int mCenterY; // 中间item的起始坐标y(不考虑偏移),当垂直滚动时,y= mCenterPosition*mItemHeight    private int mCenterX; // 中间item的起始坐标x(不考虑偏移),当垂直滚动时,x = mCenterPosition*mItemWidth    private int mCenterPoint; // 当垂直滚动时,mCenterPoint = mCenterY;水平滚动时,mCenterPoint = mCenterX    private float mLastMoveY; // 触摸的坐标y    private float mLastMoveX; // 触摸的坐标X    private float mMoveLength = 0; // item移动长度,负数表示向上移动,正数表示向下移动    private GestureDetector mGestureDetector;    private OnSelectedListener mListener;    private Scroller mScroller;    private boolean mIsFling; // 是否正在惯性滑动    private boolean mIsMovingCenter; // 是否正在滑向中间    // 可以把scroller看做模拟的触屏滑动操作,mLastScrollY为上次触屏滑动的坐标    private int mLastScrollY = 0; // Scroller的坐标y    private int mLastScrollX = 0; // Scroller的坐标x    private boolean mDisallowTouch = false; // 不允许触摸    private Paint mPaint; //    private Drawable mCenterItemBackground = null; // 中间选中item的背景色    private boolean mCanTap = true; // 单击切换选项或触发点击监听器    private boolean mIsHorizontal = false; // 是否水平滚动    private boolean mDrawAllItem = false; // 是否绘制每个item(包括在边界外的item)    @RequiresApi(api = Build.VERSION_CODES.CUPCAKE)    public ScrollPickerView(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    @TargetApi(Build.VERSION_CODES.HONEYCOMB)    @RequiresApi(api = Build.VERSION_CODES.CUPCAKE)    public ScrollPickerView(Context context, AttributeSet attrs,                            int defStyleAttr) {        super(context, attrs, defStyleAttr);        mGestureDetector = new GestureDetector(getContext(),                new FlingOnGestureListener());        mScroller = new Scroller(getContext());        mAutoScrollAnimator = ValueAnimator.ofInt(0, 0);        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);        mPaint.setStyle(Paint.Style.FILL);        init(attrs);    }    private void init(AttributeSet attrs) {        if (attrs != null) {            TypedArray typedArray = getContext().obtainStyledAttributes(attrs,                    R.styleable.ScrollPickerView);            if (typedArray.hasValue(R.styleable.ScrollPickerView_spv_center_item_background)) {                setCenterItemBackground(typedArray.getDrawable(R.styleable.ScrollPickerView_spv_center_item_background));            }            setVisibleItemCount(typedArray.getInt(                    R.styleable.ScrollPickerView_spv_visible_item_count,                    getVisibleItemCount()));            setCenterPosition(typedArray.getInt(                    R.styleable.ScrollPickerView_spv_center_item_position,                    getCenterPosition()));            setIsCirculation(typedArray.getBoolean(R.styleable.ScrollPickerView_spv_is_circulation, isIsCirculation()));            setDisallowInterceptTouch(typedArray.getBoolean(R.styleable.ScrollPickerView_spv_disallow_intercept_touch, isDisallowInterceptTouch()));            setHorizontal(typedArray.getInt(R.styleable.ScrollPickerView_spv_orientation, mIsHorizontal ? 1 : 2) == 1);            typedArray.recycle();        }    }    @Override    protected void onDraw(Canvas canvas) {        if (mData == null || mData.size() <= 0) {            return;        }        // 选中item的背景色        if (mCenterItemBackground != null) {            mCenterItemBackground.draw(canvas);        }        // 只绘制可见的item        int length = Math.max(mCenterPosition + 1, mVisibleItemCount - mCenterPosition);        int position;        int start = Math.min(length, mData.size());        if (mDrawAllItem) {            start = mData.size();        }        // 上下两边        for (int i = start; i >= 1; i--) { // 先从远离中间位置的item绘制,当item内容偏大时,较近的item覆盖在较远的上面            if (mDrawAllItem || i <= mCenterPosition + 1) {  // 上面的items,相对位置为 -i                position = mSelected - i < 0 ? mData.size() + mSelected - i                        : mSelected - i;                // 传入位置信息,绘制item                if (mIsCirculation) {                    drawItem(canvas, mData, position, -i, mMoveLength, mCenterPoint + mMoveLength - i * mItemSize);                } else if (mSelected - i >= 0) { // 非循环滚动                    drawItem(canvas, mData, position, -i, mMoveLength, mCenterPoint + mMoveLength - i * mItemSize);                }            }            if (mDrawAllItem || i <= mVisibleItemCount - mCenterPosition) {  // 下面的items,相对位置为 i                position = mSelected + i >= mData.size() ? mSelected + i                        - mData.size() : mSelected + i;                // 传入位置信息,绘制item                if (mIsCirculation) {                    drawItem(canvas, mData, position, i, mMoveLength, mCenterPoint + mMoveLength + i * mItemSize);                } else if (mSelected + i < mData.size()) { // 非循环滚动                    drawItem(canvas, mData, position, i, mMoveLength, mCenterPoint + mMoveLength + i * mItemSize);                }            }        }        // 选中的item        drawItem(canvas, mData, mSelected, 0, mMoveLength, mCenterPoint + mMoveLength);    }    /**     * 绘制item     *     * @param canvas     * @param data        数据集     * @param position   在data数据集中的位置     * @param relative   相对中间item的位置,relative==0表示中间item,relative<0表示上(左)边的item,relative>0表示下(右)边的item     * @param moveLength 中间item滚动的距离,moveLength<0则表示向上(右)滚动的距离,moveLength>0则表示向下(左)滚动的距离     * @param top        当前绘制item的坐标,当垂直滚动时为顶部y的坐标;当水平滚动时为item最左边x的坐标     */    public abstract void drawItem(Canvas canvas, List data, int position, int relative, float moveLength, float top);    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);    }    @Override    protected void onSizeChanged(int w, int h, int oldw, int oldh) {        super.onSizeChanged(w, h, oldw, oldh);        reset();    }    private void reset() {        if (mCenterPosition < 0) {            mCenterPosition = mVisibleItemCount / 2;        }        if (mIsHorizontal) {            mItemHeight = getMeasuredHeight();            mItemWidth = getMeasuredWidth() / mVisibleItemCount;            mCenterY = 0;            mCenterX = mCenterPosition * mItemWidth;            mItemSize = mItemWidth;            mCenterPoint = mCenterX;        } else {            mItemHeight = getMeasuredHeight() / mVisibleItemCount;            mItemWidth = getMeasuredWidth();            mCenterY = mCenterPosition * mItemHeight;            mCenterX = 0;            mItemSize = mItemHeight;            mCenterPoint = mCenterY;        }        if (mCenterItemBackground != null) {            mCenterItemBackground.setBounds(mCenterX, mCenterY, mCenterX + mItemWidth, mCenterY + mItemHeight);        }    }    @RequiresApi(api = Build.VERSION_CODES.FROYO)    @Override    public boolean onTouchEvent(MotionEvent event) {        if (mDisallowTouch) { // 不允许触摸            return true;        }        if (mGestureDetector.onTouchEvent(event)) {            return true;        }        switch (event.getActionMasked()) {            case MotionEvent.ACTION_MOVE:                if (mIsHorizontal) {                    if (Math.abs(event.getX() - mLastMoveX) < 0.1f) {                        return true;                    }                    mMoveLength += event.getX() - mLastMoveX;                } else {                    if (Math.abs(event.getY() - mLastMoveY) < 0.1f) {                        return true;                    }                    mMoveLength += event.getY() - mLastMoveY;                }                mLastMoveY = event.getY();                mLastMoveX = event.getX();                checkCirculation();                invalidate();                break;            case MotionEvent.ACTION_UP:                mLastMoveY = event.getY();                mLastMoveX = event.getX();                moveToCenter();                break;        }        return true;    }    /**     * @param curr     * @param end     */    private void computeScroll(int curr, int end, float rate) {        if (rate < 1) { // 正在滚动            if (mIsHorizontal) {                // 可以把scroller看做模拟的触屏滑动操作,mLastScrollX为上次滑动的坐标                mMoveLength = mMoveLength + curr - mLastScrollX;                mLastScrollX = curr;            } else {                // 可以把scroller看做模拟的触屏滑动操作,mLastScrollY为上次滑动的坐标                mMoveLength = mMoveLength + curr - mLastScrollY;                mLastScrollY = curr;            }            checkCirculation();            invalidate();        } else { // 滚动完毕            mIsMovingCenter = false;            mLastScrollY = 0;            mLastScrollX = 0;            // 直接居中,不通过动画            if (mMoveLength > 0) { //// 向下滑动                if (mMoveLength < mItemSize / 2) {                    mMoveLength = 0;                } else {                    mMoveLength = mItemSize;                }            } else {                if (-mMoveLength < mItemSize / 2) {                    mMoveLength = 0;                } else {                    mMoveLength = -mItemSize;                }            }            checkCirculation();            mMoveLength = 0;            mLastScrollY = 0;            mLastScrollX = 0;            notifySelected(true);            invalidate();        }    }    @Override    public void computeScroll() {        if (mScroller.computeScrollOffset()) { // 正在滚动            if (mIsHorizontal) {                // 可以把scroller看做模拟的触屏滑动操作,mLastScrollX为上次滑动的坐标                mMoveLength = mMoveLength + mScroller.getCurrX() - mLastScrollX;            } else {                // 可以把scroller看做模拟的触屏滑动操作,mLastScrollY为上次滑动的坐标                mMoveLength = mMoveLength + mScroller.getCurrY() - mLastScrollY;            }            mLastScrollY = mScroller.getCurrY();            mLastScrollX = mScroller.getCurrX();            checkCirculation(); // 检测当前选中的item            invalidate();        } else { // 滚动完毕            if (mIsFling) {                mIsFling = false;                moveToCenter(); // 滚动到中间位置            } else if (mIsMovingCenter) { // 选择完成,回调给监听器                mMoveLength = 0;                mIsMovingCenter = false;                mLastScrollY = 0;                mLastScrollX = 0;                notifySelected(true);            }        }    }    public void cancelScroll() {        mLastScrollY = 0;        mLastScrollX = 0;        mIsFling = mIsMovingCenter = false;        mScroller.abortAnimation();        stopAutoScroll();    }    // 检测当前选择的item位置    private void checkCirculation() {        if (mMoveLength >= mItemSize) { // 向下滑动            // 该次滚动距离中越过的item数量            int span = (int) (mMoveLength / mItemSize);            mSelected -= span;            if (mSelected < 0) {  // 滚动顶部,判断是否循环滚动                if (mIsCirculation) {                    do {                        mSelected = mData.size() + mSelected;                    } while (mSelected < 0); // 当越过的item数量超过一圈时                    mMoveLength = (mMoveLength - mItemSize) % mItemSize;                } else { // 非循环滚动                    mSelected = 0;                    mMoveLength = mItemSize;                    if (mIsFling) { // 停止惯性滑动,根据computeScroll()中的逻辑,下一步将调用moveToCenter()                        mScroller.forceFinished(true);                    }                    if (mIsMovingCenter) { //  移回中间位置                        scroll(mMoveLength, 0);                    }                }            } else {                mMoveLength = (mMoveLength - mItemSize) % mItemSize;            }        } else if (mMoveLength <= -mItemSize) { // 向上滑动            // 该次滚动距离中越过的item数量            int span = (int) (-mMoveLength / mItemSize);            mSelected += span;            if (mSelected >= mData.size()) { // 滚动末尾,判断是否循环滚动                if (mIsCirculation) {                    do {                        mSelected = mSelected - mData.size();                    } while (mSelected >= mData.size()); // 当越过的item数量超过一圈时                    mMoveLength = (mMoveLength + mItemSize) % mItemSize;                } else { // 非循环滚动                    mSelected = mData.size() - 1;                    mMoveLength = -mItemSize;                    if (mIsFling) { // 停止惯性滑动,根据computeScroll()中的逻辑,下一步将调用moveToCenter()                        mScroller.forceFinished(true);                    }                    if (mIsMovingCenter) { //  移回中间位置                        scroll(mMoveLength, 0);                    }                }            } else {                mMoveLength = (mMoveLength + mItemSize) % mItemSize;            }        }    }    // 移动到中间位置    private void moveToCenter() {        if (!mScroller.isFinished() || mIsFling || mMoveLength == 0) {            return;        }        cancelScroll();        // 向下滑动        if (mMoveLength > 0) {            if (mIsHorizontal) {                if (mMoveLength < mItemWidth / 2) {                    scroll(mMoveLength, 0);                } else {                    scroll(mMoveLength, mItemWidth);                }            } else {                if (mMoveLength < mItemHeight / 2) {                    scroll(mMoveLength, 0);                } else {                    scroll(mMoveLength, mItemHeight);                }            }        } else {            if (mIsHorizontal) {                if (-mMoveLength < mItemWidth / 2) {                    scroll(mMoveLength, 0);                } else {                    scroll(mMoveLength, -mItemWidth);                }            } else {                if (-mMoveLength < mItemHeight / 2) {                    scroll(mMoveLength, 0);                } else {                    scroll(mMoveLength, -mItemHeight);                }            }        }    }    // 平滑滚动    private void scroll(float from, int to) {        if (mIsHorizontal) {            mLastScrollX = (int) from;            mIsMovingCenter = true;            mScroller.startScroll((int) from, 0, 0, 0);            mScroller.setFinalX(to);        } else {            mLastScrollY = (int) from;            mIsMovingCenter = true;            mScroller.startScroll(0, (int) from, 0, 0);            mScroller.setFinalY(to);        }        invalidate();    }    // 惯性滑动,    private void fling(float from, float vel) {        if (mIsHorizontal) {            mLastScrollX = (int) from;            mIsFling = true;            // 最多可以惯性滑动10个item            mScroller.fling((int) from, 0, (int) vel, 0, -10 * mItemWidth,                    10 * mItemWidth, 0, 0);        } else {            mLastScrollY = (int) from;            mIsFling = true;            // 最多可以惯性滑动10个item            mScroller.fling(0, (int) from, 0, (int) vel, 0, 0, -10 * mItemHeight,                    10 * mItemHeight);        }        invalidate();    }    private void notifySelected(final boolean trigger) {        if (mListener != null) {            // 告诉监听器选择完毕            post(new Runnable() {                @Override                public void run() {                    if(mLastSelected != mSelected){                        if(trigger){                            mListener.onSelected(ScrollPickerView.this, mSelected);                        }                    }                    mLastSelected = mSelected;                }            });        }    }    private boolean mIsAutoScrolling = false;    private ValueAnimator mAutoScrollAnimator;    private final static SlotInterpolator sAutoScrollInterpolator = new SlotInterpolator();    /**     * 自动滚动(必须设置为可循环滚动)     *     * @param position     * @param duration     * @param speed    每毫秒移动的像素点     */    @RequiresApi(api = Build.VERSION_CODES.HONEYCOMB)    public void autoScrollFast(final int position, long duration, float speed, final Interpolator interpolator) {        if (mIsAutoScrolling || !mIsCirculation) {            return;        }        cancelScroll();        mIsAutoScrolling = true;        int length = (int) (speed * duration);        int circle = (int) (length * 1f / (mData.size() * mItemSize) + 0.5f); // 圈数        circle = circle <= 0 ? 1 : circle;        int aPlan = circle * (mData.size()) * mItemSize + (mSelected - position) * mItemSize;        int bPlan = aPlan + (mData.size()) * mItemSize; // 多一圈        // 让其尽量接近length        final int end = Math.abs(length - aPlan) < Math.abs(length - bPlan) ? aPlan : bPlan;        mAutoScrollAnimator.cancel();        mAutoScrollAnimator.setIntValues(0, end);        mAutoScrollAnimator.setInterpolator(interpolator);        mAutoScrollAnimator.setDuration(duration);        mAutoScrollAnimator.removeAllUpdateListeners();        if (end != 0) { // itemHeight为0导致endy=0            mAutoScrollAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {                @Override                public void onAnimationUpdate(ValueAnimator animation) {                    float rate = 0;                    rate = animation.getCurrentPlayTime() * 1f / animation.getDuration();                    computeScroll((int) animation.getAnimatedValue(), end, rate);                }            });            mAutoScrollAnimator.removeAllListeners();            mAutoScrollAnimator.addListener(new AnimatorListenerAdapter() {                @Override                public void onAnimationEnd(Animator animation) {                    super.onAnimationEnd(animation);                    mIsAutoScrolling = false;                }            });            mAutoScrollAnimator.start();        } else {            computeScroll(end, end, 1);            mIsAutoScrolling = false;        }    }    /**     * 自动滚动,默认速度为 0.6dp/ms     *     * @see ScrollPickerView#autoScrollFast(int, long, float, Interpolator)     */    @RequiresApi(api = Build.VERSION_CODES.HONEYCOMB)    public void autoScrollFast(final int position, long duration) {        float speed = dip2px(0.6f);        autoScrollFast(position, duration, speed, sAutoScrollInterpolator);    }    /**     * 自动滚动     *     * @see ScrollPickerView#autoScrollFast(int, long, float, Interpolator)     */    @RequiresApi(api = Build.VERSION_CODES.HONEYCOMB)    public void autoScrollFast(final int position, long duration, float speed) {        autoScrollFast(position, duration, speed, sAutoScrollInterpolator);    }    /**     * 滚动到指定位置     *     * @param toPosition    需要滚动到的位置     * @param duration      滚动时间     * @param interpolator     */    @RequiresApi(api = Build.VERSION_CODES.HONEYCOMB)    public void autoScrollToPosition(int toPosition, long duration, final Interpolator interpolator) {        toPosition = toPosition % mData.size();        final int endY = (mSelected - toPosition) * mItemHeight;        autoScrollTo(endY, duration, interpolator, false);    }    /**     * @param endY          需要滚动到的位置     * @param duration      滚动时间     * @param interpolator     * @param canIntercept 能否终止滚动,比如触摸屏幕终止滚动     */    @RequiresApi(api = Build.VERSION_CODES.HONEYCOMB)    public void autoScrollTo(final int endY, long duration, final Interpolator interpolator, boolean canIntercept) {        if (mIsAutoScrolling) {            return;        }        final boolean temp = mDisallowTouch;        mDisallowTouch = !canIntercept;        mIsAutoScrolling = true;        mAutoScrollAnimator.cancel();        mAutoScrollAnimator.setIntValues(0, endY);        mAutoScrollAnimator.setInterpolator(interpolator);        mAutoScrollAnimator.setDuration(duration);        mAutoScrollAnimator.removeAllUpdateListeners();        mAutoScrollAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {            @Override            public void onAnimationUpdate(ValueAnimator animation) {                float rate = 0;                rate = animation.getCurrentPlayTime() * 1f / animation.getDuration();                computeScroll((int) animation.getAnimatedValue(), endY, rate);            }        });        mAutoScrollAnimator.removeAllListeners();        mAutoScrollAnimator.addListener(new AnimatorListenerAdapter() {            @Override            public void onAnimationEnd(Animator animation) {                super.onAnimationEnd(animation);                mIsAutoScrolling = false;                mDisallowTouch = temp;            }        });        mAutoScrollAnimator.start();    }    /**     * 停止自动滚动     */    @TargetApi(Build.VERSION_CODES.HONEYCOMB)    public void stopAutoScroll() {        mIsAutoScrolling = false;        mAutoScrollAnimator.cancel();    }    private static class SlotInterpolator implements Interpolator {        @Override        public float getInterpolation(float input) {            return (float) (Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;        }    }    /**     * 快速滑动时,惯性滑动一段距离     *     * @author huangziwei     */    private class FlingOnGestureListener extends GestureDetector.SimpleOnGestureListener {        private boolean mIsScrollingLastTime = false;        public boolean onDown(MotionEvent e) {            if (mDisallowInterceptTouch) {  // 不允许父组件拦截事件                ViewParent parent = getParent();                if (parent != null) {                    parent.requestDisallowInterceptTouchEvent(true);                }            }            mIsScrollingLastTime = isScrolling(); // 记录是否从滚动状态终止            // 点击时取消所有滚动效果            cancelScroll();            mLastMoveY = e.getY();            mLastMoveX = e.getX();            return true;        }        @Override        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,                               final float velocityY) {            // 惯性滑动            if (mIsInertiaScroll) {                cancelScroll();                if (mIsHorizontal) {                    fling(mMoveLength, velocityX);                } else {                    fling(mMoveLength, velocityY);                }            }            return true;        }        @RequiresApi(api = Build.VERSION_CODES.HONEYCOMB)        @Override        public boolean onSingleTapUp(MotionEvent e) {            mLastMoveY = e.getY();            mLastMoveX = e.getX();            float lastMove = 0;            if (isHorizontal()) {                mCenterPoint = mCenterX;                lastMove = mLastMoveX;                LogUtils.e("lastMove===",lastMove+"");                LogUtils.e("mCenterPoint===",mCenterPoint+"");            } else {                mCenterPoint = mCenterY;                lastMove = mLastMoveY;            }            if (mCanTap && !isScrolling() && !mIsScrollingLastTime) {                if (lastMove >= mCenterPoint && lastMove <= mCenterPoint + mItemSize) {                    //performClick();                } else if (lastMove < mCenterPoint) {                    int bs = (int)((mCenterPoint+mItemSize) - lastMove)/mItemSize;                    int move = bs*mItemSize;                    autoScrollTo(move, 150, sAutoScrollInterpolator, false);                } else if (lastMove > mCenterPoint + mItemSize) {                    int bs = (int)((lastMove -mCenterPoint)/mItemWidth);                    int move = -bs*mItemSize;                    autoScrollTo(move, 150, sAutoScrollInterpolator, false);                } else {                    moveToCenter();                }            } else {                moveToCenter();            }            return true;        }    }    public List getData() {        return mData;    }    public void setData(List data) {        if (data == null) {            mData = new ArrayList();        } else {            this.mData = data;        }        mSelected = mData.size() / 2;        invalidate();    }    public T getSelectedItem() {        return mData.get(mSelected);    }    public int getSelectedPosition() {        return mSelected;    }    public void setSelectedPosition(int position,boolean trigger) {        if (position < 0 || position > mData.size() - 1                || position == mSelected) {            return;        }        mSelected = position;        invalidate();        if (mListener != null) {            notifySelected(trigger);        }    }    public void setOnSelectedListener(OnSelectedListener listener) {        mListener = listener;    }    public OnSelectedListener getListener() {        return mListener;    }    public boolean isInertiaScroll() {        return mIsInertiaScroll;    }    public void setInertiaScroll(boolean inertiaScroll) {        this.mIsInertiaScroll = inertiaScroll;    }    public boolean isIsCirculation() {        return mIsCirculation;    }    public void setIsCirculation(boolean isCirculation) {        this.mIsCirculation = false;    }    public boolean isDisallowInterceptTouch() {        return mDisallowInterceptTouch;    }    public int getVisibleItemCount() {        return mVisibleItemCount;    }    public void setVisibleItemCount(int visibleItemCount) {        mVisibleItemCount = visibleItemCount;        reset();        invalidate();    }    /**     * 是否允许父元素拦截事件,设置true后可以保证在ScrollView下正常滚动     */    public void setDisallowInterceptTouch(boolean disallowInterceptTouch) {        mDisallowInterceptTouch = disallowInterceptTouch;    }    public int getItemHeight() {        return mItemHeight;    }    public int getItemWidth() {        return mItemWidth;    }    /**     * @return 当垂直滚动时,mItemSize = mItemHeight;水平滚动时,mItemSize = mItemWidth     */    public int getItemSize() {        return mItemSize;    }    /**     * @return 中间item的起始坐标x(不考虑偏移), 当垂直滚动时,x = mCenterPosition*mItemWidth     */    public int getCenterX() {        return mCenterX;    }    /**     * @return 中间item的起始坐标y(不考虑偏移), 当垂直滚动时,y= mCenterPosition*mItemHeight     */    public int getCenterY() {        return mCenterY;    }    /**     * @return 当垂直滚动时,mCenterPoint = mCenterY;水平滚动时,mCenterPoint = mCenterX     */    public int getCenterPoint() {        return mCenterPoint;    }    public boolean isDisallowTouch() {        return mDisallowTouch;    }    /**     * 设置是否允许手动触摸滚动     *     * @param disallowTouch     */    public void setDisallowTouch(boolean disallowTouch) {        mDisallowTouch = disallowTouch;    }    /**     * 中间item的位置,0 <= centerPosition <= mVisibleItemCount     *     * @param centerPosition     */    public void setCenterPosition(int centerPosition) {        if (centerPosition < 0) {            mCenterPosition = 0;        } else if (centerPosition >= mVisibleItemCount) {            mCenterPosition = mVisibleItemCount - 1;        } else {            mCenterPosition = centerPosition;        }        mCenterY = mCenterPosition * mItemHeight;        invalidate();    }    /**     * 中间item的位置,默认为 mVisibleItemCount / 2     *     * @return     */    public int getCenterPosition() {        return mCenterPosition;    }    public void setCenterItemBackground(Drawable centerItemBackground) {        mCenterItemBackground = centerItemBackground;        mCenterItemBackground.setBounds(mCenterX, mCenterY, mCenterX + mItemWidth, mCenterY + mItemHeight);        invalidate();    }    public void setCenterItemBackground(int centerItemBackgroundColor) {        mCenterItemBackground = new ColorDrawable(centerItemBackgroundColor);        mCenterItemBackground.setBounds(mCenterX, mCenterY, mCenterX + mItemWidth, mCenterY + mItemHeight);        invalidate();    }    public Drawable getCenterItemBackground() {        return mCenterItemBackground;    }    public boolean isScrolling() {        return mIsFling || mIsMovingCenter || mIsAutoScrolling;    }    public boolean isFling() {        return mIsFling;    }    public boolean isMovingCenter() {        return mIsMovingCenter;    }    public boolean isAutoScrolling() {        return mIsAutoScrolling;    }    public boolean isCanTap() {        return mCanTap;    }    /**     * 设置 单击切换选项或触发点击监听器     *     * @param canTap     */    public void setCanTap(boolean canTap) {        mCanTap = canTap;    }    public boolean isHorizontal() {        return mIsHorizontal;    }    public boolean isVertical() {        return !mIsHorizontal;    }    public void setHorizontal(boolean horizontal) {        if (mIsHorizontal == horizontal) {            return;        }        mIsHorizontal = horizontal;        reset();        if (mIsHorizontal) {            mItemSize = mItemWidth;        } else {            mItemSize = mItemHeight;        }        invalidate();    }    public void setVertical(boolean vertical) {        if (mIsHorizontal == !vertical) {            return;        }        mIsHorizontal = !vertical;        reset();        if (mIsHorizontal) {            mItemSize = mItemWidth;        } else {            mItemSize = mItemHeight;        }        invalidate();    }    public boolean isDrawAllItem() {        return mDrawAllItem;    }    public void setDrawAllItem(boolean drawAllItem) {        mDrawAllItem = drawAllItem;    }    /**     * @author huangziwei     */    public interface OnSelectedListener {        void onSelected(ScrollPickerView scrollPickerView, int position);    }    public int dip2px(float dipVlue) {        DisplayMetrics metrics = getContext().getResources().getDisplayMetrics();        float sDensity = metrics.density;        return (int) (dipVlue * sDensity + 0.5F);    }    @Override    public void setVisibility(int visibility) {        super.setVisibility(visibility);        if (visibility == VISIBLE) {            moveToCenter();        }    }}

ColorUtil 类

package com.demo.utils;import android.graphics.Color;/** * 颜色工具栏 */public class ColorUtil {    /**     * 计算渐变后的颜色     *     * @param startColor 开始颜色     * @param endColor   结束颜色     * @param rate       渐变率(0,1)     * @return 渐变后的颜色,当rate=0时,返回startColor,当rate=1时返回endColor     */    public static int computeGradientColor(int startColor, int endColor, float rate) {        if (rate < 0) {            rate = 0;        }        if (rate > 1) {            rate = 1;        }        int alpha = Color.alpha(endColor) - Color.alpha(startColor);        int red = Color.red(endColor) - Color.red(startColor);        int green = Color.green(endColor) - Color.green(startColor);        int blue = Color.blue(endColor) - Color.blue(startColor);        return Color.argb(                Math.round(Color.alpha(startColor) + alpha * rate),                Math.round(Color.red(startColor) + red * rate),                Math.round(Color.green(startColor) + green * rate),                Math.round(Color.blue(startColor) + blue * rate));    }}

调用

        /**         * 温度         */        airTemperatureView = new AirTemperatureView(context);        LinearLayout.LayoutParams airTemperatureView_Params = new LinearLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,Axis.scaleX(230));        airTemperatureView_Params.setMargins(0,Axis.scaleX(100),0,0);        bodyLayout.addView(airTemperatureView,airTemperatureView_Params);//父布局 addView()        airTemperatureView.setOnTemperatureListener(new AirTemperatureView.TemperatureListener() {            @Override            public void setAirTemper(int temperature) {                LogUtils.e("空调温度===",temperature+"");                setTemperature(temperature);//网络请求方法            }        });

更多相关文章

  1. Android Studio Gradle多渠道打包(动态设定App名称,应用图标,背景
  2. Android根据经纬度获取位置信息
  3. 设置listview中的item的颜色
  4. Android开发 - 丰富常用的颜色文件colors.xml
  5. Android P SystemUI下拉时,状态栏和通知栏显示位置不一致。
  6. android 颜色 获取
  7. Android中保存并设置ListView位置
  8. Android:改变 Toolbar 的文字和溢出图标颜色

随机推荐

  1. Android(安卓)StepView物流进度
  2. 安卓不知道怎么学?看十年码农如何回答这个
  3. Android实现系统关机和重启
  4. MVC架构设计与三层模型 & MVP思想精髓与
  5. Android mediaplayer 播放本地音乐文件
  6. Unity3D for Android 纹理压缩支持
  7. Android 版本兼容适配
  8. Android Studio中获取sha1证书指纹数据的
  9. [置顶] Android原生(Native)C(JNI/NDK)开
  10. Android中ViewPager+Fragment懒加载问题