zoukankan      html  css  js  c++  java
  • Android-自定义开关(ViewGroup版)

    虽然实现自定义开关,通常情况下都是继承View,比较合理方便快捷一些

    但是我今天想去继承ViewGroup来实现自定义开关来玩玩

    效果图:

     

    布局代码:

    <!-- 自定义开关ViewGroup版 -->
    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:myswitch="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".upgrade.MainActivity">
    
        <custom.view.upgrade.my_switch_viewgroup.MySwitch2
            android:layout_width="200dp"
            android:layout_height="200dp"
            android:layout_centerInParent="true"
            android:background="#33F00000">
    
        </custom.view.upgrade.my_switch_viewgroup.MySwitch2>
    
    </RelativeLayout>

    效果:

    布局代码:

    <!-- 自定义开关ViewGroup版 -->
    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:myswitch="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".upgrade.MainActivity">
    
        <custom.view.upgrade.my_switch_viewgroup.MySwitch2
            android:layout_width="200dp"
            android:layout_height="200dp"
            android:layout_centerInParent="true"
            android:background="#33F00000">
    
            <!-- 第一个子控件 -->
            <ImageView
                android:id="@+id/iv_switch_bg"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@mipmap/switch_background"/>
    
            <!-- 第二个子控件 -->
            <ImageView
                android:id="@+id/iv_switch_drag"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@mipmap/switch_drag"/>
    
        </custom.view.upgrade.my_switch_viewgroup.MySwitch2>
    
    </RelativeLayout>

    自定义开关继承ViewGroup代码:

    package custom.view.upgrade.my_switch_viewgroup;
    
    import android.content.Context;
    import android.graphics.Canvas;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.view.MotionEvent;
    import android.view.View;
    import android.view.ViewGroup;
    
    public class MySwitch2 extends ViewGroup implements View.OnClickListener , View.OnTouchListener {
    
        private static final String TAG = MySwitch2.class.getSimpleName();
    
        private View switchBackground;
        private View switchGrag;
    
        private int switchBackgroundWidth;
        private int switchBackgroundHeight;
        private int switchGragWidth;
        private int switchGragHeight;
    
        private boolean onCreate = false;
    
        // 开关的状态
        private boolean switchStatus;
    
        public MySwitch2(Context context, AttributeSet attrs) {
            super(context, attrs);
    
            // 如果是这样写的话,是给整个粉红色正方形区域都设置了点击事件
            // setOnClickListener(this);
        }
    
        @Override
        protected void onFinishInflate() {
            super.onFinishInflate();
    
            switchBackground = getChildAt(0);
            switchGrag = getChildAt(1);
    
            onCreate = true;
    
            // 给子控件设置点击事件
            switchBackground.setOnClickListener(this);
            switchGrag.setOnClickListener(this);
    
            // 给子控件设置Touch事件
            switchBackground.setOnTouchListener(this);
            switchGrag.setOnTouchListener(this);
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    
            // 测量第一个子控件
            LayoutParams switchBgParams = switchBackground.getLayoutParams();
            switchBackground.measure(switchBgParams.width, switchBgParams.height);
    
            // 测量第二个子控件
            LayoutParams switchGragParams = switchGrag.getLayoutParams();
            switchGrag.measure(switchGragParams.width, switchGragParams.height);
    
            // -2 代表是wrap_content
            // Log.d(TAG, "测量方法>>> switchGragParams.width" + switchGragParams.width);
    
            // 得到测量后的高和宽
            if (onCreate) {
                onCreate = false;
                switchBackgroundWidth = switchBackground.getMeasuredWidth();
                switchBackgroundHeight = switchBackground.getMeasuredHeight();
                switchGragWidth = switchGrag.getMeasuredWidth();
                switchGragHeight = switchGrag.getMeasuredHeight();
            }
    
            // 在拖动开关的时候,测量会执行很多次,因为在拖动的过程中,开关Grag会的测量宽度会不断变化
            // Log.d(TAG, "测量方法>>> switchBackgroundWidth:" + switchBackgroundWidth + " switchGragWidth:" + switchGragWidth);
        }
    
        @Override
        protected void onLayout(boolean changed, int l, int t, int r, int b) {
            // 给子控件排版指定位置
            switchBackground.layout(
                    getMeasuredWidth() / 2 - switchBackground.getWidth() / 2,
                    getMeasuredHeight() / 2 - switchBackground.getHeight() / 2,
                    switchBackground.getMeasuredWidth() + (getMeasuredWidth() / 2 - switchBackground.getWidth() / 2),
                    switchBackground.getMeasuredHeight() + (getMeasuredHeight() / 2 - switchBackground.getHeight() / 2));
    
            /*switchGrag.layout(
                    getMeasuredWidth() / 2 - (switchGrag.getWidth() / 2),
                    getMeasuredHeight()  /2 - (switchGrag.getHeight() / 2),
                    switchGrag.getMeasuredWidth() + getMeasuredWidth() / 2 - (switchGrag.getWidth() / 2),
                    switchGrag.getMeasuredHeight() + getMeasuredHeight()  /2 - (switchGrag.getHeight() / 2));*/
    
            int gragL = getMeasuredWidth() / 2 - (switchBackground.getWidth() / 2);
            int gragT = getMeasuredHeight()  / 2 - (switchGrag.getHeight() / 2);
            switchGrag.layout(
                    gragL,
                    gragT,
                    switchGrag.getMeasuredWidth() + gragL,
                    switchGrag.getMeasuredHeight() + gragT);
    
            // 动的是两个子控件
            // scrollTo(90, 0);
        }
    
        /**
         * 打开开关
         * @return
         */
        /*private int getOpenSwitch() {
            return getMeasuredWidth() / 2;
        }*/
    
        /**
         * 关闭开关
         * @return
         */
        /*private int getCloseSwitch() {
            return getMeasuredWidth() / 2 - (switchBackground.getWidth() / 2);
        }*/
    
        /**
         * 开关滑动的按钮
         * @param move
         */
        private void setScrollMove(int move) {
    
            int countValue = (switchBackground.getMeasuredWidth() - switchGrag.getMeasuredWidth()) / 2;
    
            int countValue2 = (switchBackgroundWidth - switchGragWidth);
    
            // Log.d(TAG, "switchBackgroundWidth:" + switchBackgroundWidth + " switchGragWidth:" + switchGragWidth);
    
            Log.d(TAG, "move:" + move + " countValue:" + countValue +
                    " getMeasuredWidth():" + switchGrag.getMeasuredWidth()
                  + " getWidth():" + switchGrag.getWidth() + " countValue2:" +countValue2);
    
            if (move < 0) {
                move = 0;
            } else if (move > countValue2) {
                Log.d(TAG, "移动到最右边....");
                move = countValue2;
            }
            // switchGrag.setPadding(move, 0, 0, 0);
            setPaddingAction(move);
        }
    
        /**
         * 注意!这个是当前MySwitch2 ViewGroup的Touch事件
         * @param event
         * @return
         */
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            return super.onTouchEvent(event);
        }
    
        /**
         * 此方法并不去绘制任何东西,Android自动回去绘制的
         * @param canvas
         */
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
        }
    
        /**
         * 是否可以点击
         */
        private boolean isClick = true;
    
        @Override
        public void onClick(View v) {
            Log.d(TAG, "onClick() >>>>>>>>>>>>>>>> run");
            Log.d(TAG, "onClick() isClick:" + isClick);
            if (isClick) {
                if (!switchStatus) {
                    // 说明是关闭状态,我要打开
                    moveResult = (switchBackgroundWidth - switchGragWidth);
                } else {
                    moveResult = 0;
                }
                switchGrag.setPadding(moveResult, 0, 0, 0);
            }
        }
    
    
        private float downX;
        private int moveResult;
        private float downTempX;
    
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            boolean touchResult = false;
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    downX = event.getX();
                    touchResult = false;
                    downTempX = downX;
                    isClick = true;
                    break;
                case MotionEvent.ACTION_MOVE:
                    moveResult += (int) (event.getX() - downX);
                    setScrollMove(moveResult);
                    downX = event.getX();
    
                    if (Math.abs(event.getX() - downTempX) > 5) {
                        // 说明在滑动,就onTouch来消费掉了,不给onClick点击事件了
                        touchResult = true;
                        Log.d(TAG, "说明在滑动,就onTouch来消费掉了,不给onClick点击事件了");
                        isClick = false;
                    }
                    break;
                case MotionEvent.ACTION_UP:
                    // int upLeft = 0;
                    if (moveResult > (switchBackgroundWidth - switchGragWidth) / 2) {
                        moveResult = switchBackgroundWidth - switchGragWidth;
                    } else if (moveResult < (switchBackgroundWidth - switchGragWidth) / 2) {
                        moveResult = 0;
                    } else if (moveResult <= 0){
                        moveResult = 0;
                    }
                    setPaddingAction(moveResult);
                    break;
                default:
                    break;
            }
            return touchResult;
        }
    
        private void setPaddingAction(int value) {
            if (value > (switchBackgroundWidth - switchGragWidth) / 2) {
                switchStatus = true;
            } else if (value < (switchBackgroundWidth - switchGragWidth) / 2) {
                switchStatus = false;
            } else if (value <= 0){
                switchStatus = false;
            }
            switchGrag.setPadding(value, 0,0,0);
        }
    }
  • 相关阅读:
    数据库表的常见设计规则总结
    关于记录log日志的几种方法
    lambda表达式
    java8之stream和lambda表达式
    Andriod底层第三课-----启动流程2(Zygote)
    Andriod底层第三课---启动流程
    Andriod底层第二课-----编译系统
    Andriod 底层第一课----JNI
    Andriod 第八课----传感器
    Andriod第七课----ContentProvide
  • 原文地址:https://www.cnblogs.com/android-deli/p/9702229.html
Copyright © 2011-2022 走看看