zoukankan      html  css  js  c++  java
  • Android自定义滑动开关按钮

    一、效果图

    二、主要技术点

      1.自定义View

      2.自定义属性

    三、自定义控件的步骤

      1.自定义类继承自View或View的子类;

      2.重写构造方法

        (1)MyView(Context);  // 在代码中new 对象时调用此方法 

        (2)MyView(Context,AttributeSet);  // 在XML布局文件中声明此View,创建对象时,由系统自动调用

        (3)MyView(Context,AttributeSet,int);  // 与方法2用法一样,只是多了一个参数:默认样式

      3.重写相关方法,实现我们的需求,一般要重写的方法:

        (1)onMeasure(int,int);  // 系统测量控件大小时调用该方法 

        (2)onLayout(boolean,int,int,int,int);  // 系统为该view 指定位置时调用此方法,子view的位置,自身只有建议权,决定权在父view的手中。一般不需要重写。

        (3)onDraw(Canvas);  // 为本view绘制内容时,调用该方法。

    四、为新控件添加自定义属性的步骤:

      1.在attrs.xml文件中声明属性,有属性名(name)和格式(format)。如 

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
    
        <!-- 声明属性集的名称 -->
        <declare-styleable name="MyToggleBtn">
            <!-- 声名一个属性  name是my_background   类型为 引用类型      引用资源ID -->
            <attr name="my_background" format="reference" />
            <!-- 声名一个属性  name是my_slide_btn   类型为 引用类型      引用资源ID -->
            <attr name="my_slide_btn" format="reference" />
            <!-- 声名一个属性  name是curr_state   类型为 boolean 类型 -->
            <attr name="curr_state" format="boolean" />
        </declare-styleable>
    
    </resources>

      2.在布局文件中使用新属性,使用之前必须先声明命名空间,如xmlns:gnnuit="http://schemas.android.com/apk/res/com.gnnuit.togglebutton",其中“http://schemas.android.com/apk/res/”为Android固定的格式,“com.gnnuit.togglebutton”为应用程序的包名,与AndroidManifest.xml声明的包名一样。

    <com.gnnuit.togglebutton.MyToggleButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            gnnuit:curr_state="true"
            gnnuit:my_background="@drawable/switch_background"
            gnnuit:my_slide_btn="@drawable/slide_button" />

      3.在自定义View的构造方法中,通过解析AttributeSet对象,获得所需要的属性值。

    四。核心代码

    package com.gnnuit.togglebutton;
    
    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.graphics.Canvas;
    import android.graphics.Paint;
    import android.util.AttributeSet;
    import android.view.MotionEvent;
    import android.view.View;
    
    public class MyToggleButton extends View implements android.view.View.OnClickListener {
        private Bitmap backgroundBitmap;// 背景图片
        private Bitmap slideButtonBitmap;// 滑动按钮图片
        private Paint paint;
        private boolean currentState = false;// 当前状态
        private float left_slide;// 滑动按钮的左边界位置
        private float startX, lastX;// 记录滑动按钮滑动时的开始和结束位置
        private boolean isSlide = false;// 记录是否移动滑动按钮
        private float dist;
    
        /**
         * 在布局文件中声明此View,创建时由系统自动调用该构造方法
         * 
         * @param context
         * @param attrs
         */
        public MyToggleButton(Context context, AttributeSet attrs) {
            super(context, attrs);
            // 获取自定义属性
            currentState = attrs.getAttributeBooleanValue("http://schemas.android.com/apk/res/com.gnnuit.togglebutton", "curr_state", false);
            
            int backgroundResourceId = attrs.getAttributeResourceValue("http://schemas.android.com/apk/res/com.gnnuit.togglebutton", "my_background", -1);
            if (backgroundResourceId == -1) {
                throw new RuntimeException("请设置背景图片");
            }
            backgroundBitmap = BitmapFactory.decodeResource(getResources(), backgroundResourceId);
            
            int slideBtnResourceId = attrs.getAttributeResourceValue("http://schemas.android.com/apk/res/com.gnnuit.togglebutton", "my_slide_btn", -1);
            if (slideBtnResourceId == -1) {
                throw new RuntimeException("请设置背景图片");
            }
            slideButtonBitmap = BitmapFactory.decodeResource(getResources(), slideBtnResourceId);
    
            if (currentState) {
                left_slide = backgroundBitmap.getWidth() - slideButtonBitmap.getWidth();
            }
            initView();// 初始化
        }
    
        /**
         * 初始化
         */
        private void initView() {
            // 初始化图片
            // backgroundBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.switch_background);
            // slideButtonBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.slide_button);
            // 初始化画笔
            paint = new Paint();
            paint.setAntiAlias(true);// 设置抗锯齿
            // 设置点击事件
            setOnClickListener(this);
        }
    
        @Override
        /**
         * 测量尺寸的回调方法
         */
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            setMeasuredDimension(backgroundBitmap.getWidth(), backgroundBitmap.getHeight());// 设置控件的宽和高,单位是像素
        }
    
        @Override
        /**
         * 绘制当前View的内容
         */
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            canvas.drawBitmap(backgroundBitmap, 0, 0, paint);
            canvas.drawBitmap(slideButtonBitmap, left_slide, 0, paint);
        }
    
        @Override
        public void onClick(View v) {
            if (!isSlide) {
                currentState = !currentState;
                flushState();// 刷新界面
            }
        }
    
        /**
         * 刷新当前状态
         */
        private void flushState() {
            if (currentState) {
                left_slide = backgroundBitmap.getWidth() - slideButtonBitmap.getWidth();
            } else {
                left_slide = 0;
            }
            invalidate();
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            super.onTouchEvent(event);
            switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                isSlide = false;
                startX = lastX = event.getX();
                break;
    
            case MotionEvent.ACTION_MOVE:
                lastX = event.getX();
                dist = lastX - startX;
                if (Math.abs(dist) > 5) {
                    isSlide = true;
                    left_slide += dist;
                    flushShow();
                    startX = event.getX();
                }
                break;
            case MotionEvent.ACTION_UP:
                if (isSlide) {
                    if (left_slide > (backgroundBitmap.getWidth() - slideButtonBitmap.getWidth()) / 2) {
                        left_slide = backgroundBitmap.getWidth() - slideButtonBitmap.getWidth();
                        currentState = true;
                    } else {
                        left_slide = 0;
                        currentState = false;
                    }
                    flushShow();
                }
                break;
            }
            return true;
        }
    
        /**
         * 刷新当前View
         */
        private void flushShow() {
            int maxLeftSlide = backgroundBitmap.getWidth() - slideButtonBitmap.getWidth();
            // left_slide的范围为0=<left_slide<=maxLeftSlide
            if (left_slide > maxLeftSlide) {
                left_slide = maxLeftSlide;
                currentState = true;
            } else if (left_slide < 0) {
                left_slide = 0;
                currentState = false;
            }
            invalidate();
        }
    }
  • 相关阅读:
    self 和 super 关键字
    NSString类
    函数和对象方法的区别
    求两个数是否互质及最大公约数
    TJU Problem 1644 Reverse Text
    TJU Problem 2520 Quicksum
    TJU Problem 2101 Bullseye
    TJU Problem 2548 Celebrity jeopardy
    poj 2586 Y2K Accounting Bug
    poj 2109 Power of Cryptography
  • 原文地址:https://www.cnblogs.com/FlySheep/p/3938776.html
Copyright © 2011-2022 走看看