天天看點

自定義滑動開關按鈕-SwitchButton

最近,在項目開發中需要用到開關按鈕,因為業務需求,需要适應自己的App style,是以決定親自實操一遍,自定義一個控件。
業務需求:
    1.開關點選事件
    2.開關滑動事件
    3.涉及了動态測量繪制文本的寬高
先上效果圖,如下:
           
自定義滑動開關按鈕-SwitchButton
因為比較簡單,沒有自定義屬性,注釋比較完整,是以貼上完整代碼給你們參考,有問題可以私聊。
           

完整代碼如下:

public class AutoButton extends View implements View.OnTouchListener{
    //開關背景圖
    private Bitmap bgBitmap;
    //開關按鈕圖
    private Bitmap btnBitmap;
    private Paint paint;
    //标記開關滑動的值
    private int leftDis=;
    //标記開關滑動的最大值
    private int slidingMax;
    //設定開關對應的文本
    private final String text1="開";
    private final String text2="關;
    //标記開關狀态
    private boolean mCurrent;
    //标記點選事件
    private boolean isClickable;
    //标記滑動事件
    private boolean isMove;
    //開關打開的事件監聽器
    private SoftFloorListener softFloorListener;
    //開關關閉的事件監聽器
    private HydropowerListener hydropowerListener;
    //标記開關文本的寬度
    float width1,width2;
    //記錄文本中心點 cx1:繪制文本1的x坐标  cx2:繪制文本2的x坐标  
    //cy記錄繪制文本的高度
    float cx1,cy,cx2;
    //代碼執行個體化需要的方法
    public AutoButton(Context context) {
        this(context,null);
    }
    //在xml布局時需要用到的方法
    public AutoButton(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }

    public AutoButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView();
    }

    //初始化資料
    private void initView() {
    //加載背景圖
        bgBitmap= BitmapFactory.decodeResource(getResources(), R.drawable.bg_switchbutton);
    //加載開關按鈕圖    btnBitmap=BitmapFactory.decodeResource(getResources(),R.drawable.btn_switchbutton);
        paint=new Paint();
        slidingMax=bgBitmap.getWidth()-btnBitmap.getWidth();
        paint.setTextSize(35);
        //測量繪制文本1的寬度
        width1= paint.measureText(text1);
        //測量文本的寬度
        Paint.FontMetricsInt fontMetricsInt=paint.getFontMetricsInt();

        cy=btnBitmap.getHeight()/2+(fontMetricsInt.descent-fontMetricsInt.ascent)/2;
        width2= paint.measureText(text2);
        cx2=(bgBitmap.getWidth()*2-btnBitmap.getWidth())/2-width2/2;
        paint.setAntiAlias(true);
        setOnTouchListener(this);
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  //根據加載圖檔設定控件的大小 
  setMeasuredDimension(bgBitmap.getWidth(),bgBitmap.getHeight());

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //繪制背景圖
        canvas.drawBitmap(bgBitmap,0,0,paint);
        //繪制按鈕圖
        canvas.drawBitmap(btnBitmap,leftDis,0,paint);
        //根據不同狀态繪制不同顔色,不同位置的文本
        if (mCurrent){
            paint.setColor(Color.WHITE);
            canvas.drawText(text2,cx2,cy,paint);
            paint.setColor(Color.BLACK);
            canvas.drawText(text1,cx1,cy,paint);
        }else {
            paint.setColor(Color.WHITE);
            canvas.drawText(text1,cx1,cy,paint);
            paint.setColor(Color.BLACK);
            canvas.drawText(text2,cx2,cy,paint);
        }


    }



    //根據事件重新整理視圖
    private void flushView() {
        mCurrent=!mCurrent;
        if (mCurrent){
            leftDis=slidingMax;
            if (hydropowerListener!=null){
            //按鈕打開監聽器
                hydropowerListener.hydropower();
            }
        }else {
            leftDis=0;
            if (softFloorListener!=null){
            //按鈕關閉監聽器
                softFloorListener.softFloor();
            }
        }
        invalidate();
    }

    //startX 标記手指按下的X坐标,  lastX 标記移動後的x坐标
    //disX 标記x方向移動的距離
    float startX,lastX,disX;
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                isClickable=true;
                startX=event.getX();
                isMove=false;
                break;
            case MotionEvent.ACTION_MOVE:
                lastX=event.getX();
                disX=lastX-startX;
                //設定一個移動的門檻值
                if (Math.abs(disX)<5) break;
                isMove=true;
                isClickable=false;
                moveBtn();
                startX=event.getX();
                break;
            case MotionEvent.ACTION_UP:
                //點選事件
                if (isClickable){
                    flushView();
                }
                //滑動事件
                if (isMove){
                    if (leftDis>slidingMax/2){
                        mCurrent=false;
                    }else {
                        mCurrent=true;
                    }
                    flushView();
                }
                break;
        }

        return true;
    }


    //按鈕滑動時的位置控制
    private void moveBtn() {
        leftDis+=disX;
        if (leftDis>slidingMax){
            leftDis=slidingMax;
        }else if (leftDis<0){
            leftDis=0;
        }
        invalidate();
    }


    //設定按鈕打開監聽器
    public void setSoftFloorListener(SoftFloorListener softFloorListener){
        this.softFloorListener=softFloorListener;
    }

    //設定按鈕關閉監聽器
    public void setHydropowerListener(HydropowerListener hydropowerListener){
        this.hydropowerListener=hydropowerListener;
    }

    //設定按鈕打開監聽器接口
    public interface SoftFloorListener{
        void softFloor();
    }

    //設定按鈕打開監聽器接口
    public interface HydropowerListener{
        void hydropower();
    }
}

           

繼續閱讀