android多指触屏事件响应(界面包含ScrollView时冲突处理)

项目需求:想在界面上实现双指向左、向右、向上、向下滑屏时触发不同的事件进行响应。

项目中遇到的问题:

1、Activity中重写onTouchEvent事件触发冲突

1)当Activity中不包含ScrollView时,重写onTouchEvent事件,会被触发;

2)当Activity中包含ScrollView时,ScrollView会消费掉onTouch事件,把Activity的onTouchEvent事件拦截,此时在Activity中重写onTouchEvent事件,是不会被触发的。

解决办法:重写界面上需要触发双指的View,在自定义View中重写onTouchEvent事件。

2、MotionEvent事件多指触屏时机判断

在网上搜索都是如下知识点:event.getAction()有以下几个触发事件

  • ACTION_DOWN:触控时,总是第一个被触发,之后就不会再触发
  • ACTION_POINTER_DOWN:只要还有触控点在屏幕上,之后手指下去都是之触发这个事件
  • ACTION_UP:触控点离开时,仅当最后一个触控点消失时才会触发
  • ACTION_POINTER_UP:只要还有触控点在屏幕上,每当手指离开都会触发这个事件
  • ACTION_MOVE:可以获取按下触控点的位置(getX和getY)

按上面的理解,ACTION_POINTER_DOWN应该是大于等于两个手指触屏时才会被触发,可本人亲测的是,即使一个手指触屏,也会触发ACTION_POINTER_DOWN事件,按这个来判断是否有双指触屏不靠谱,应该用event.getPointerCount()来判断是否有多手指触屏

3、自定义View双指触屏事件拦截

主要通过重写onTouchEvent方法,在MotionEvent.ACTION_MOVE事件中判断当有双指触摸时,请求父控件不要拦截触屏事件getParent().requestDisallowInterceptTouchEvent(true);,交给子控件自己处理,然后在MotionEvent.ACTION_UP中把控制权交回getParent().requestDisallowInterceptTouchEvent(false);。

public class MyTextView extends TextView {
    private int oldX1 = 0, oldX2 = 0, oldY1 = 0, oldY2 = 0, newX1 = 0, newY1 = 0, newX2 = 0, newY2 = 0, mScrollPointerId1, mScrollPointerId2;
    private boolean hasTwoFinger = false;
    private Context context;

    public MyTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        final int actionIndex = event.getActionIndex();//获取当前事件的索引

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mScrollPointerId1 = event.getPointerId(actionIndex);
                oldX1 = (int)event.getX();
                oldY1 = (int)event.getY();
            case MotionEvent.ACTION_POINTER_DOWN://即使只有一个手指触屏,也会触发此事件
                mScrollPointerId2 = event.getPointerId(actionIndex);
                oldX2 = (int)event.getX();//event.getX(0)是当前屏幕追踪手指的X轴位置
                oldY2 = (int)event.getY();//event.getY(0)是当前屏幕追踪手指的Y轴位置
                break;
            case MotionEvent.ACTION_POINTER_UP://第二个手指抬起
                if (event.getPointerId(actionIndex) == mScrollPointerId1) {//判断离开屏幕的手指是不是当前追踪的手指
                    newX1 = (int)event.getX();
                    newY1 = (int)event.getY();
                } else {
                    newX2 = (int)event.getX();
                    newY2 = (int)event.getY();
                }
                break;

            case MotionEvent.ACTION_MOVE:
                //不想要父视图拦截触摸事件
                if (event.getPointerCount() == 2) {
                    getParent().requestDisallowInterceptTouchEvent(true);
                }

                break;
            case MotionEvent.ACTION_UP:
                if (event.getPointerId(actionIndex) == mScrollPointerId1) {//判断离开屏幕的手指是不是当前追踪的手指
                    newX1 = (int)event.getX();
                    newY1 = (int)event.getY();
                } else {
                    newX2 = (int)event.getX();
                    newY2 = (int)event.getY();
                }
                int distanceX1 = newX1 - oldX1;
                int distanceY1 = newY1 - oldY1;
                int distanceX2 = newX2 - oldX2;
                int distanceY2 = newY2 - oldY2;
                //Y方向上的
                    if (Math.abs(distanceY1) > Math.abs(distanceX1) && Math.abs(distanceY2) > Math.abs(distanceX2)) {
                        if (distanceY1 > 0 && distanceY2 > 0) {//向下滑动
                            showShortToast("向下滑动");
                        } else if (distanceY1 < 0 && distanceY2 < 0) {//向上滑动
                            showShortToast("向上滑动");
                        }
                    } else if(Math.abs(distanceY1) < Math.abs(distanceX1) && Math.abs(distanceY2) < Math.abs(distanceX2)){//X轴方向
                        if (distanceX1 > 0 && distanceX2 > 0) {//向右滑动
                            showShortToast("向右滑动");
                        } else if (distanceX1 < 0 && distanceX2 < 0) {//向左滑动
                            showShortToast("向左滑动");
                        }
                    }
               
                getParent().requestDisallowInterceptTouchEvent(false);

                break;

            default:
                break;
        }

        return true;
    }

    private void showShortToast(String text) {
        Toast.makeText(context, text, Toast.LENGTH_SHORT).show();
    }
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值