Android 自定义控件----自定义开关--事件的冲突(点击事件和触摸事件)

一个视图从创建到显示过程中的主要方法:
1.构造方法实例化类

    public MyToggleButton(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initView();
    }
    private void initView() {
        bavkgroundBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.a);
        slidingBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.b);
        slideLeftMax  = bavkgroundBitmap.getWidth() - slidingBitmap.getWidth();
        paint=new Paint();
        paint.setAntiAlias(true);//设置抗锯齿

        setOnClickListener(this);

    }

2.测量maesure(int,int) onMeasure 如果是viewgroup ,还要测量孩子

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        setMeasuredDimension(bavkgroundBitmap.getWidth(),bavkgroundBitmap.getHeight());

    }

3.指定位置 layout() onLayout() 指定控件的位置,一般view不用写,viewgroup的时候才需要
4.绘制视图 draw() onDraw(canvas)

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawBitmap(bavkgroundBitmap,0,0,paint);
        canvas.drawBitmap(slidingBitmap,slideLeft,0,paint);
    }

onTouchEvent:

@Override
public boolean onTouchEvent(MotionEvent event) {
    super.onTouchEvent(event);
    switch (event.getAction()){
        case MotionEvent.ACTION_DOWN://手指按下
            break;
        case MotionEvent.ACTION_MOVE://手指滑动
            break;
        case MotionEvent.ACTION_UP://手指离开
            break;
    }

    return true;
}

实现开关的点击事件,点击开关按钮的时候为打开或为关闭:

private boolean isOpen=false; //默认打开
    @Override
    public void onClick(View v) {
            isOpen = !isOpen;
            flushView();
    }

    private void flushView() {
        if(isOpen){
            slideLeft = slideLeftMax;
        }else
        {
            slideLeft=0;
        }
        invalidate();//会导致onDraw()执行
    }

实现滑动功能,自动回弹功能,在手指滑到接近开的位置时为关闭状态,当接近关的位置时为打开状态:

    private float startX;
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        super.onTouchEvent(event);
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                //1.记录按下的坐标
                startX = event.getX();
                break;
            case MotionEvent.ACTION_MOVE:
                //2.计算结束值
                float endX=event.getX();
                //3.计算偏移量
                float distance = endX - startX;
                slideLeft = (int) (slideLeft + distance);
                //4.屏蔽非法值
                if(slideLeft < 0){
                    slideLeft = 0;

                }else if(slideLeft > slideLeftMax){
                    slideLeft = slideLeftMax;
                }
                //5.刷新
                invalidate();
                //6.数据还原
                startX = event.getX();

                break;
            case MotionEvent.ACTION_UP:
                    if(slideLeft > slideLeftMax/2){
                        isOpen = true;
                    }else {
                        isOpen = false;
                    }
                    flushView();

                break;
        }

        return true;
    }

解决点击事件和触摸事件的冲突:

private boolean isEnableClick = true;//点击事件生效
    @Override
    public void onClick(View v) {
        if(isEnableClick) {
            isOpen = !isOpen;
            flushView();
        }
    }

设置只要手指滑动一点点,就认为是滑动,此时点击事件失效:

private float lastX;
lastX = startX = event.getX();
                if(Math.abs(endX - lastX) > 5){
                    isEnableClick= false;
                }

当点击事件生效的时候开关按钮不回弹,当点击事件失效的时候实现回弹。

            case MotionEvent.ACTION_UP:
                if(!isEnableClick){
                    if(slideLeft > slideLeftMax/2){
                        isOpen = true;
                    }else {
                        isOpen = false;
                    }
                    flushView();
                }

源码:

public class MyToggleButton extends View implements View.OnClickListener{
    private Bitmap bavkgroundBitmap;
    private Bitmap slidingBitmap;
    private int slideLeftMax;
    private Paint paint;
    private int slideLeft;

    public MyToggleButton(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initView();
    }

    private void initView() {
        bavkgroundBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.a);
        slidingBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.b);
        slideLeftMax  = bavkgroundBitmap.getWidth() - slidingBitmap.getWidth();
        paint=new Paint();
        paint.setAntiAlias(true);//设置抗锯齿

        setOnClickListener(this);

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        setMeasuredDimension(bavkgroundBitmap.getWidth(),bavkgroundBitmap.getHeight());

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawBitmap(bavkgroundBitmap,0,0,paint);
        canvas.drawBitmap(slidingBitmap,slideLeft,0,paint);
    }

    private boolean isOpen=false;
    private boolean isEnableClick = true;//点击事件生效
    @Override
    public void onClick(View v) {
        if(isEnableClick) {
            isOpen = !isOpen;
            flushView();
        }
    }


    private void flushView() {
        if(isOpen){
            slideLeft = slideLeftMax;
        }else
        {
            slideLeft=0;
        }
        invalidate();//会导致onDraw()执行
    }

    private float startX;
    private float lastX;
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        super.onTouchEvent(event);
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                //1.记录按下的坐标
                lastX = startX = event.getX();
                break;
            case MotionEvent.ACTION_MOVE:
                //2.计算结束值
                float endX=event.getX();
                //3.计算偏移量
                float distance = endX - startX;
                slideLeft = (int) (slideLeft + distance);
                //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 {
                        isOpen = false;
                    }
                    flushView();
                }

                break;
        }

        return true;
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值