Android 怎么自定义绘制一个切换按钮(一)

这是我参与11月更文挑战的第24天,活动详情查看:2021最后一次更文挑战

前言

Android 开发系统自带很多常用的系统控件,文本的,图片的,按钮的,进度条的,下拉列表的等等,一些手机中比较常用的控件,Android系统都会提供,一般只要在原有的控件基础上做一些简单的修改,就可以实现开发中很多设计要求的图或者操作控件,但是我们不能用仅用Android自带的控件,我们也要学会通过学习Android的系统源码,了解view的绘制流程,去实现自己写一个View供我们自己使用,学以致用,才是学习的最终目的。

实现一个自定义切换按钮

image.png

类似这样的,支持开关,禁用等功能。

准备工作

想要实现上面UI给的设计图,首先需要把要实现的View所包含的元素了解清楚,切换按钮也就是开关按钮,有开有关,这个是必不可少的,开关也可以不让使用,所以还需要有一个禁用的状态,从图中可以看出,要绘制,首先要拆分,怎么拆分呢,首先是开按钮,可以拆成底色,然后还有个圆球,再就是外层的白色蒙层,然后关闭按钮,底色,圆球,白色蒙层,仔细看,外层还有个灰色的外框,统一一下,就是:
1.底色
2.圆球
3.白色蒙层
4.外层边框

初始化一些需要使用的元素

public class MySwitchButton extends View {

    private int openColor = 0xFF1a81d1;//默认打开色值
    private int closeColor = 0xFFD0D0D0;//默认关闭色值
    private int strokeColor;//边框色值
    private int strokeWidth;//边框宽度
    private int strokeRound;//边框的圆角
    private int switchWidth = 100;//开关宽度
    private int switchHeight = 50;//开关高度
    private int int rimSize = 3;//边缘间距

    /****画笔****/
    private Paint openPaint;//开启的画笔
    private Paint closePaint;//关闭的画笔
    private Paint paintCircle;//圆球画笔
    /****形状****/
    private Rect backRect;//背景的背景形状
    private Rect frontRect;//阴影的形状

    private RectF closeRect;//关闭的背景形状
    private RectF lineCircleRect;//边框的形状
    private RectF frontCircleRect;//圆球
    private RectF backCircleRect;//阴影的形状


    /****透明度****/
    private int enableAlpha;//开启的透明度
    private int disableAlpha;//关闭的透明度
    private boolean enable = true;
    
    public MySwitchButton(Context context) {
        this(context, null);
    }

    public MySwitchButton(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MySwitchButton(Context context, @Nullable AttributeSet attrs, int     defStyleAttr) {
        super(context, attrs, defStyleAttr);
        
        initAttrs(context, attrs);
    }
    
/***
 * 初始化属性配置
 * @param context
 * @param attrs
 */
protected void initAttrs(Context context, @Nullable AttributeSet attrs) {
    openPaint = new Paint();
    closePaint = new Paint();
    paintCircle = new Paint();
    openPaint.setAntiAlias(true);
    closePaint.setAntiAlias(true);
    paintCircle.setAntiAlias(true);
    if (attrs != null) {
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MySwitchButton);
        openColor = typedArray.getColor(R.styleable.MySwitchButton_switch_open_color, getResources().getColor(R.color.open_color_default));
        closeColor = typedArray.getColor(R.styleable.MySwitchButton_switch_close_color, getResources().getColor(R.color.close_color_default));
        enable = typedArray.getBoolean(R.styleable.MySwitchButton_switch_enable, true);
        typedArray.recycle();
    }
    strokeColor = getContext().getResources().getColor(R.color.transparent_10);
}
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int width = measureDimension(DEFAULT_WIDTH, widthMeasureSpec);
        int height = measureDimension(DEFAULT_HEIGHT, heightMeasureSpec);
        //如果设置的宽度小于高度,重置宽度为高度的2倍
        if (shape == SHAPE_CIRCLE) {
            if (width < height) width = height * 2;
        }
        setMeasuredDimension(width, height);
        initDrawingVal();
    }
    /***
     * 根据mode 重新赋值
     * @param defaultSize
     * @param measureSpec
     * @return
     */
    private int measureDimension(int defaultSize, int measureSpec) {
        int result;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);
        if (specMode == MeasureSpec.EXACTLY) {
            result = specSize;
        } else {
            result = defaultSize;
            if (specMode == MeasureSpec.AT_MOST) {
                result = Math.min(result, specSize);
            }
        }
        return result;
    }
    /***
     * 绘制椭圆
     */
    private void initDrawingVal() {
        int width = getMeasuredWidth();
        int height = getMeasuredHeight();

        backCircleRect = new RectF();
        frontCircleRect = new RectF();
        frontRect = new Rect();
        backRect = new Rect(0, 0, width, height);
        closeRect = new RectF(0, 0, width, height);

        lineCircleRect = new RectF(STROKE_SIZE, STROKE_SIZE, width - STROKE_SIZE, height - STROKE_SIZE);

        if (isOpen) {
            enableAlpha = 255;
        } else {
            enableAlpha = 0;
        }
        if (!enable) {
            disableAlpha = 80;
        }
    }
    
}

复制代码

初始化工作差不多了,attrs文件,后面会补上,简单看下都是些基础的自定义view的通用初始化工作,再把外层的椭圆画完,基本的准备工作差不多了。后面会着重把绘制的主体实现,也就是onDraw()方法,onTouchEvent()事件的处理。

猜你喜欢

转载自juejin.im/post/7034891747649912862