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();
        }
    }
  • 相关阅读:
    SharePoint缓存配置
    修改默认的个人站点
    生成代码工具
    Ext 布局(layout)
    编程网站
    EXT 4.0 上传文件
    修改Ext grid 单元格
    Ext.tip.Tooltip 提示
    EXT iframe 应用
    EXT 4.0 TreeGrid 使用
  • 原文地址:https://www.cnblogs.com/FlySheep/p/3938776.html
Copyright © 2011-2022 走看看