3. 自定义控件(3)

自定义组件之滑动开关

/**
 * @author WuMeng
 * @date 2019/1/2
 * Describe:
 * 一个视图从创建到显示过程中的主要方法:
 * 1. 构造方法实例化类
 * 2. 测量-measure(int,int)---> onMeasure();
 * 如果当前View是一个ViewGroup,还有义务测量孩子,孩子有建议权
 * 3. 指定位置-layout()---> onLayout();
 * 指定控件的位置,一般View不用写这个方法,ViewGroup的时候才需要,一般View不需要重写该方法
 * 4. 绘制视图-draw()---> onDraw()
 * 根据上面两个方法参数,进行绘制
 *
 */
public class MyToggleButton extends View implements View.OnClickListener {

    /**
     * 背景图
     */
    private Bitmap backgroundBitmap;
    /**
     * 上面的滑块
     */
    private Bitmap slideBitmap;

    /**
     * 画笔
     */
    private Paint paint;

    /**
     * 距离左边的最大距离
     */
    private int slideLeftMax;

    /**
     * 开关是否打开
     */
    private boolean isOpen = false;

    /**
     * 距离左边的距离
     */
    private int slideLeft;

    /**
     * 在代码中new实例化时调用
     * @param context
     */
    public MyToggleButton(Context context) {
        super(context);
    }

    /**
     * 在布局文件中声明View的时候,该方法由系统调用
     * 如果我们在布局文件中使用该类,将会使用这个构造方法实例化该类,如果没有就崩溃
     * @param context
     * @param attrs
     */
    public MyToggleButton(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initView();
    }

    /**
     * 增加一个默认显示样式时候使用
     * @param context
     * @param attrs
     * @param defStyleAttr
     */
    public MyToggleButton(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    private void initView() {
        paint = new Paint();
        // 设置抗锯齿
        paint.setAntiAlias(true);
        // 图片解析为Bitmap
        backgroundBitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.switch_background);
        slideBitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.slide_button);
        slideLeftMax = backgroundBitmap.getWidth() - slideBitmap.getWidth();

        // 设置点击事件
        this.setOnClickListener(this);
    }

    /**
     * 视图的测量
     * @param widthMeasureSpec
     * @param heightMeasureSpec
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        // 保存测量结果
        setMeasuredDimension(backgroundBitmap.getWidth(),backgroundBitmap.getHeight());
    }

    /**
     * 视图的绘制
     * @param canvas
     */
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawBitmap(backgroundBitmap,0,0,paint);
        canvas.drawBitmap(slideBitmap,slideLeft,0,paint);
    }

    @Override
    public void onClick(View v) {
        if (isEnableClick) {
            isOpen = !isOpen;
            flushView();
        }

    }

    private float startX;
    private float lastX;
    private boolean isEnableClick = true;

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        super.onTouchEvent(event);
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                // 1.记录按下的坐标
                lastX = startX = event.getX();
                isEnableClick = true;
                break;
            case MotionEvent.ACTION_MOVE:
                // 2. 计算结束值
                float endX = event.getX();
                // 3. 计算偏移量
                float distanceX = endX - startX;
                slideLeft = (int) (slideLeft + distanceX);
                // 4.屏蔽非法值
                if (slideLeft < 0) {
                    slideLeft = 0;
                } else if (slideLeft > slideLeftMax) {
                    slideLeft = slideLeftMax;
                }
                // 5. 刷新
                invalidate();
                // 6. 数据还原
                startX = event.getX();

                if (Math.abs(endX - lastX) > 5) {
                    isEnableClick = false;
                }
                break;
            case MotionEvent.ACTION_UP:
                if (!isEnableClick) {
                    if (slideLeft > slideLeftMax / 2) {
                        isOpen = true;
                    } else if (slideLeft < slideLeftMax / 2){
                        isOpen = false;
                    }
                    flushView();
                }

                break;
            default:
                break;
        }
        return true;
    }

    private void flushView() {
        if (isOpen) {
            slideLeft = slideLeftMax;
        } else {
            slideLeft = 0;
        }

        // 会导致onDraw()重新被调用
        invalidate();
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_34390996/article/details/87060460
3.