美文网首页
自定义控件之-----ToggleButton

自定义控件之-----ToggleButton

作者: 我是你森哥哥 | 来源:发表于2017-06-08 09:44 被阅读0次

    先来张效果图

    banner.gif

    步骤思路

    • 继承View
      1、测量自己的宽高
      2、绘制自己
      3、处理触摸事件

    1、继承View

    
    
            public class MyToggleButton extends View {
                public MyToggleButton(Context context, AttributeSet attrs, int defStyle) {
                    super(context, attrs, defStyle);
                }
            
                // 在布局文件中使用控件时 调用
                public MyToggleButton(Context context, AttributeSet attrs) {
                    super(context, attrs);
                }
            
                // 在代码中new对象时 调用
                public MyToggleButton(Context context) {
                    super(context);
                }
            }
    
    

    2、在布局中使用MyToggleButton

    
            <com.itheima.toggle94.MyToggleButton
            android:id="@+id/toggle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    
    
    

    3、测量宽高

    
    
            // 测量自己的宽高,把背景图片的宽高设置为自己的宽高
            @Override
            protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
                super.onMeasure(widthMeasureSpec, heightMeasureSpec);
                // 把背景图片的宽高设置为自己的宽高
                setMeasuredDimension(backgroundBitmap.getWidth(), backgroundBitmap.getHeight());
            }
    
            // 外界设置开关背景图片资源
            public void setBackgroundRes(int backgroundRes){
                // 把传进来的图片资源 转换成Bitmap对象
                backgroundBitmap = BitmapFactory.decodeResource(getResources(), backgroundRes);
            }
    
    
    

    4、绘制

    
    
    
            // 外界设置滑动块图片资源
            public void setSlideButtonRes(int slideButtonRes){
                // 把传进来的图片资源 转换成Bitmap对象
                slideButtonBitmap = BitmapFactory.decodeResource(getResources(), slideButtonRes);
            }
    
            // 绘制自己
            @Override
            protected void onDraw(Canvas canvas) {
                super.onDraw(canvas);
                // 绘制背景
                canvas.drawBitmap(backgroundBitmap, 0, 0, null);
                // 绘制滑动块
                canvas.drawBitmap(slideButtonBitmap, 0, 0, null);
            }
    
    
    

    5、根据状态绘制滑动块

    
    
            // 外界设置开关状态
            public void setState(boolean state){
                this.currentState = state;
            }
    
            protected void onDraw(Canvas canvas) {
                super.onDraw(canvas);
                // 绘制背景
                canvas.drawBitmap(backgroundBitmap, 0, 0, null);
                // 绘制滑动块 根据外界的设置,展示开或关
                if(!currentState){// 关状态
                    canvas.drawBitmap(slideButtonBitmap, 0, 0, null);
                }else{// 开状态
                    canvas.drawBitmap(slideButtonBitmap, backgroundBitmap.getWidth()-slideButtonBitmap.getWidth(), 0, null);
                }
            }
    
    

    6、处理事件,让滑动块随手指移动

    
    
            @Override
            public boolean onTouchEvent(MotionEvent event) {
                switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    isTouching = true;
                    // 获取手指触摸时相对于自己的x位置
                    currentX = (int) event.getX();
                    break;
                case MotionEvent.ACTION_MOVE:
                    currentX = (int) event.getX();
                    break;
                case MotionEvent.ACTION_UP:
                    isTouching = false;
                    currentX = (int) event.getX();
                    break;
        
                default:
                    break;
                }
                // 重新绘制控件,重新调用onDraw
                invalidate();
                return true;// 消费掉事件
            }
    
            protected void onDraw(Canvas canvas) {
                super.onDraw(canvas);
                // 绘制背景
                canvas.drawBitmap(backgroundBitmap, 0, 0, null);
                
                // 根据手指触摸的位置绘制滑动块图片
                if(isTouching){
                    canvas.drawBitmap(slideButtonBitmap, currentX, 0, null);
                }else{
                    // 绘制滑动块 根据外界的设置,展示开或关
                    if(!currentState){// 关状态
                        canvas.drawBitmap(slideButtonBitmap, 0, 0, null);
                    }else{// 开状态
                        canvas.drawBitmap(slideButtonBitmap, backgroundBitmap.getWidth()-slideButtonBitmap.getWidth(), 0, null);
                    }
                }
            }
    
    

    7、让用户感觉手指触摸到了滑动块中间

    
    
            protected void onDraw(Canvas canvas) {
                super.onDraw(canvas);
                // 绘制背景
                canvas.drawBitmap(backgroundBitmap, 0, 0, null);
                
                // 根据手指触摸的位置绘制滑动块图片
                if(isTouching){
                    int left = currentX-slideButtonBitmap.getWidth()/2;// 让滑动块画的中心画到手指触摸的位置
                    // 限制滑动块的滑动范围
                    if(left<0){// 如果超出左边,直接绘制到0位置
                        left = 0;
                    }else if(left>backgroundBitmap.getWidth()-slideButtonBitmap.getWidth()){
                        left = backgroundBitmap.getWidth()-slideButtonBitmap.getWidth();
                    }
                    canvas.drawBitmap(slideButtonBitmap, left, 0, null);
                }else{
                    ......
                }
            }
    
    

    8、手指抬起时,通过改变当前状态,让滑动块根据状态绘制

    
    
            case MotionEvent.ACTION_UP:
                isTouching = false;
                currentX = (int) event.getX();
                // 手指抬起时,根据手指触摸的位置与背景图片一半比较,离哪边近,滑动块就滑动到哪
                currentState = currentX>backgroundBitmap.getWidth()/2;
                
                break;
    
            default:
                break;
            }
    
    

    9、对外暴露监听,让外界监听到开关的状态变化

    
    
            * 1、暴露接口
    
                // 对外暴露开关状态发生变化的接口
                public interface OnToggleButtonStateChangeListener{
                    // 当开关状态发生变化时 调用
                    void onStateChanged(boolean state);
                }
    
            * 2、对外提供监听器
    
                // 让外界设置状态变化的监听器
                public void setOnToggleButtonStateChangeListener(OnToggleButtonStateChangeListener listener){
                    this.mListener = listener;
                }
    
            * 3、当状态发生变化时调用监听器的回调方法
    
                case MotionEvent.ACTION_UP:
                isTouching = false;
                currentX = (int) event.getX();
                // 手指抬起时,根据手指触摸的位置与背景图片一半比较,离哪边近,滑动块就滑动到哪
                // 当状态发生变化时,调用外界传递进来的监听器的onStateChanged
                boolean tempState = currentX>backgroundBitmap.getWidth()/2;
                if(tempState!=currentState){// 状态发生变化
                    currentState = tempState;
                    if(mListener!=null){
                        mListener.onStateChanged(currentState);
                    }
                }
                break;
    
            * 4、外界监听开关状态
    
                OnToggleButtonStateChangeListener listener = new OnToggleButtonStateChangeListener() {
                
                    @Override
                    public void onStateChanged(boolean state) {
                        // 处理业务
                        Toast.makeText(getApplicationContext(), ""+state, 0).show();
                    }
                };
                toggle.setOnToggleButtonStateChangeListener(listener);
    

    10、自定义属性

    
    
            * 1、定义属性
    
                /toggle94/res/values/attrs.xml
    
                <declare-styleable name="MytoggleButton">
                    <!-- 背景图片属性 -->
                    <attr name="backgroundRes" format="reference" />
                    <!-- 滑动块图片属性 -->
                    <attr name="slideButtonRes" format="reference" />
                    <!-- 开关状态属性 -->
                    <attr name="state" format="boolean" />
                </declare-styleable>
    
            * 2、在布局中使用属性,要先声明命名空间
    
                <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                    xmlns:itheima="http://schemas.android.com/apk/res/com.itheima.toggle94"
                    xmlns:tools="http://schemas.android.com/tools"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:paddingBottom="@dimen/activity_vertical_margin"
                    android:paddingLeft="@dimen/activity_horizontal_margin"
                    android:paddingRight="@dimen/activity_horizontal_margin"
                    android:paddingTop="@dimen/activity_vertical_margin"
                    tools:context=".MainActivity" >
                
                    <com.itheima.toggle94.MyToggleButton
                        android:id="@+id/toggle"
                        itheima:backgroundRes="@drawable/switch_background"
                        itheima:slideButtonRes="@drawable/slide_button_background"
                        itheima:state="false"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content" />
                
                </RelativeLayout>
    
            * 3、代码中获取自定义属性值,设置给控件
    
                // 在布局文件中使用控件时 调用
                public MyToggleButton(Context context, AttributeSet attrs) {
                    super(context, attrs);
                    // 从布局文件中获取控件的自定义属性值
                    
                    String namespace = "http://schemas.android.com/apk/res/com.itheima.toggle94";
                    int backgroundResValue = attrs.getAttributeResourceValue(namespace, "backgroundRes", 0);
                    setBackgroundRes(backgroundResValue);
                    
                    int slideButtonResValue = attrs.getAttributeResourceValue(namespace, "slideButtonRes", 0);
                    setSlideButtonRes(slideButtonResValue);
                    
                    currentState = attrs.getAttributeBooleanValue(namespace, "state", false);
                }
    
    

    相关文章

      网友评论

          本文标题:自定义控件之-----ToggleButton

          本文链接:https://www.haomeiwen.com/subject/ocyzfxtx.html