android自定义选择开关switchButon

android自定义选择开关按钮,能够实现滑动改变状态操作,点击改变状态操作,对外提供监听器可以捕获改变后的状态和当前状态的名称,可以在xml中指定初始时的状态,也可以在代码中动态设置开关的状态

具体的效果图如下(开关下方是textview用于显示改变后的状态和状态的文字名称)

(1)关闭状态下

(2)开启状态

(3)滑动过程中

        滑动过程中不响应状态改变,监听器不会有反应,只有松开按钮时才会响应:当开关滑动的距离大于宽度的1/2时状态才会发生变化,否则会重新滑动回原来的状态

相关的代码(只贴相对重要的代码,具体的工程源代码会上传到我的资源中去,需要的可以自己去下载)

view的onDraw()方法中分两种情况进行绘制

分四个区域绘制:左边半圆形,右边半圆形,中间的矩形其实是分两段的这么做主要是为了处理滑动过程中颜色填充的问题(左边显示一种色调,右边显示一种)

开关当前处于开启状态时绘制:根据movX判断移动的距离绘制圆形按钮的所在位置


if (state){//开启状态
            RadioX=canvas.getWidth() - height / 2;
      
            if (movX<=0&&movX>height-canvas.getWidth()){
                paint.setColor(switchColorTrue);
            }
           else {
                paint.setColor(switchColorFalse);
            }
            RectF rectleft=new RectF(0,0,height,height);

            canvas.drawArc(rectleft,90,180,true,paint);
            RectF rectRight=new RectF(canvas.getWidth()-height,0,canvas.getWidth(),height);
           
            if (movX==0){
                paint.setColor(switchColorTrue);
            }
            else {
                paint.setColor(switchColorFalse);
            }
            canvas.drawArc(rectRight, 270, 180, true, paint);

            //右矩形
            paint.setColor(switchColorFalse);
            canvas.drawRect(canvas.getWidth() - height / 2 + movX, 0, canvas.getWidth() - height / 2+1, height, paint);
            //左矩形
//            if (movX<=3*height/2-canvas.getWidth()){
//                paint.setColor(switchColorFalse);
//            }
//            3*height/2-canvas.getWidth();
//            else {
//                paint.setColor(switchColorTrue);
//            }
            paint.setColor(switchColorTrue);
            canvas.drawRect(height/2, 0, canvas.getWidth() - height/2+movX, height, paint);

        
            paint.setColor(ballColor);
            canvas.drawCircle(RadioX+movX, height / 2, height / 2-1, paint);

            paint.setColor(textColor);
            paint.setTextSize(textSize);
            String text="";
            Typeface typeface= Typeface.create(Typeface.DEFAULT_BOLD,Typeface.BOLD);
            paint.setTypeface(typeface);
            paint.setTextAlign(Paint.Align.CENTER);
            Paint.FontMetrics metrics=paint.getFontMetrics();
            float des=metrics.descent;
            float asent=metrics.ascent;
            float he=(des+asent)/2;

            if (movX<=-height/2){
                text=falseText;
                canvas.drawText(text,0,text.length(),(canvas.getWidth()-height)/2+height,
                        canvas.getHeight()/2-he,paint);
            }
//闭合状态下的绘制思路大致与开启时相同,只是初始的圆心坐标不一样,就不再贴出来了

2.重写onTouchEvent响应滑动以及点击事件

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                    movX=0;
                eveX=event.getX();
                float eventY=event.getY();
                if (eveX>=0&&eveX<=getWidth()&&eventY>=0&&eventY<=getHeight()){
                    isMove=true;
                }
                else {
                    isMove=false;
                }
                Log.i("isMove======",""+isMove);
                break;
            case MotionEvent.ACTION_MOVE:
                if (isMove){//按下去的点在当前空间范围内响应操作
                    movX=event.getX()-eveX;//X轴上移动的距离
                    if (state){//开启状态
                        if (movX<=0){
                            if (movX<height-getWidth()){
                                movX=height-getWidth();
                            }
                        }
                       else {
                            movX=0;
                        }

                    }
                    else {//关闭状态
                        if (movX>=0){
                            if (movX>getWidth()-height){
                                movX=getWidth()-height;
                            }
                        }
                       else {
                            movX=0;
                        }
                    }
                }
                invalidate();
                break;
在滑动和点击过程中不响应状态改变,只有松开时对状态判断然后响应状态改变
如果是滑动后抬起,对移动的距离和抬起的位置进行判断,然后决定是否改变开关状态
 case MotionEvent.ACTION_UP:
//                处理点击事件
                float X=event.getX();
                float Y=event.getY();
                float mvX=X-eveX;
                movX=0;
                if (isMove){//滑动事件
                    isMove=false;
                    if (state){//开启状态
                        if (mvX<=-height/2){
                            state=!state;
                            //关闭状态
                            if (listener!=null){
                                listener.change(state,falseText);
                            }
                        }
                        else if (mvX==0){//点击事件
                            state=!state;
                            //关闭状态
                            if (listener!=null){
                                if (state){
                                    listener.change(state,trueText);//监听器响应监听回调
                                }
                                else {
                                    listener.change(state,falseText);
                                }
                            }
                        }
                    }
                    else {//关闭状态
                        if (mvX>=height/2){
                            state=!state;
                            if (listener!=null){
                                listener.change(state,trueText);
                            }
                        }
                        else if (mvX==0){//点击事件
                            state=!state;
                            //关闭状态
                            if (listener!=null){
                                if (state){
                                    listener.change(state,trueText);
                                }
                               else {
                                    listener.change(state,falseText);
                                }
                            }
                        }
                    }
                    invalidate();
                }
                break;
        }
        return true;
    }

监听器:实现的原理就是接口回调,定义一个接口在该类中由接口的实现对象进行响应操作,然后该对象获取到操作时的参数(其实就是虚拟一个不存在的实例化该接口的对象,由该对象调用相关的方法,然后该对象获取到需要的数据)

public void setSwitchChangerListener(switchChangeListener li){
    this.listener=li;
}
interface switchChangeListener{
    void change(Boolean sta,String text);
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值