效果图

代码实现

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(安卓)widget—Gallery学习笔记
  2. Android(安卓)setting中添加桌面循环滑动选项
  3. Android(安卓)获取View的位置参数:x,y和相对父容器的偏移量以及中
  4. Android(安卓)- ScrollView嵌套ListView~使ListView不滚动
  5. [置顶] android滑动基础篇
  6. android中滑动SQLite数据库分页加载
  7. android 横向滚动屏幕实现(3)
  8. Android(安卓)TextView文字过多时,通过滚动条显示多余内容
  9. 收藏的Android非常好用的组件或者框架

随机推荐

  1. Android studio Gradle home can not be
  2. Android图形显示系统——概述
  3. Android API demos 阅读笔记
  4. 系统总结归纳一下android
  5. Android的Intent Filter详解
  6. 作为一个IOS\android开发者,转行到RN的
  7. Android(安卓)Input Framework(二)---Eve
  8. Android 开发者从0到1发布一个微信小程序
  9. Android的跨进程通信介绍---------------
  10. Android 7 强势来袭开发者们不得不知道的