天天看点

自定义滑动开关按钮-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();
    }
}

           

继续阅读