Android 自定義控制元件 按鈕滾動選擇

cswhale發表於2018-01-16

效果圖

這裡寫圖片描述

程式碼實現

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<CharSequence> 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<CharSequence> {


    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<CharSequence>(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<CharSequence> 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<T> 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<T> 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<T> 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<T> getData() {
        return mData;
    }

    public void setData(List<T> data) {
        if (data == null) {
            mData = new ArrayList<T>();
        } 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);//網路請求方法
            }
        });

相關文章