四、触摸事件

本文详细解析了Android中触摸事件的处理流程,包括dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent及onTouch等方法的调用顺序及其作用,并通过具体测试代码验证了理论分析。

一直想写一篇文章记录一下.今天终于写了,比拿超神还要爽

触摸事件的常用方法

onTouch //处理触摸事件
onTouchEvent //处理触摸事件,如果onTouch已经执行并返回true,这个将不执行
dispatchTouchEvent //事件派发
onInterceptTouchEvent//事件拦截
requestDisallowInterceptTouchEvent//是否允许拦截

onTouch

 public boolean onTouch(View v, MotionEvent event) {       
    return true;//返回true.onTouchEvent不执行
 }

onTouchEvent

true.派发到下一个界面
false不派发
观察View的onTouchEvent实际处理了OnClickOnLongClick

dispatchTouchEvent

触摸事件派发

true 派发到子view
false 不派发

onInterceptTouchEvent

事件拦截

true拦截
false 不拦截 

requestDisallowInterceptTouchEvent

一般用于在子类是否将事件传递给父类

false 父类进行拦截
true 父类不拦截.子类自己处理

结论测试

调用顺序.

猜想

dispatchTouchEvent -> onInterceptTouchEvent ->onTouch ->onTouchEvent

测试代码

public class TouchTestLayout extends LinearLayout implements View.OnTouchListener{
    private static final String TAG = "TouchTestLayout";

    public TouchTestLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.setOnTouchListener(this);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.e(TAG,"onTouchEvent");
        return super.onTouchEvent(event);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        Log.e(TAG,"onInterceptTouchEvent");
        return super.onInterceptTouchEvent(ev);
    }


    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        Log.e(TAG,"dispatchTouchEvent");
        return super.dispatchTouchEvent(ev);
    }


    @Override
    public boolean onTouch(View v, MotionEvent event) {
        Log.e(TAG,"onTouch");
        return false;
    }
}

测试结果

TouchTestLayout: dispatchTouchEvent
TouchTestLayout: onInterceptTouchEvent
TouchTestLayout: onTouch
TouchTestLayout: onTouchEvent

证明我们的结论是对的

添加子view的调用顺序

现在给TouchTestLayout添加一个子view

<cn.ifreedomer.com.asynctaskdemo.TouchTestLayout
      android:id="@+id/testLayout"
      android:layout_width="match_parent"
      android:layout_height="match_parent">
      <cn.ifreedomer.com.asynctaskdemo.TestChildTextView
          android:layout_width="match_parent"
          android:layout_height="match_parent"/>
  </cn.ifreedomer.com.asynctaskdemo.TouchTestLayout>

TestChildTextView的代码很简单

public class TestChildTextView extends TextView implements View.OnTouchListener {
    private static final String TAG = "TestChildTextView";
    public TestChildTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        setOnTouchListener(this);
    }
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.e(TAG,"onTouchEvent");
        return super.onTouchEvent(event);
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        Log.e(TAG,"onTouch");
        return false;
    }
}

运行结果
这里写图片描述
派发的过程明眼人一眼就看出来.就是传给子类,子类再回传回来

 父dispatchTouchEvent -> 父onInterceptTouchEvent ->子view的onTouch -> 子类onTouchEvent ->父类onTouch ->父类onTouchEvent

事件拦截

这个比较简单我就简单的测试一下.false不拦截,子类能接受。true拦截,子类收不到.用上面的代码,修改TouchTestLayout的onInterceptTouchEvent

 @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        Log.e(TAG,"onInterceptTouchEvent");
        return true;
    }

测试结果

这里写图片描述

requestDisallowInterceptTouchEvent(disallowIntercept)

作用

源码文档:disallowIntercept True if the child does not want the parent to intercept touch events.(这里就不测试了.官方文档没啥好测的)
(如果子类不想父类拦截触摸事件.disallowIntercept = true)

使用场景

onInterceptTouchEvent会全部拦截.
但是有时我们是有条件的拦截.比如ViewPagerOut里面嵌套了一个ViewPagerInner. ViewPagerOut当里面滑倒尽头可以联动.当ViewPagerInner滑到最左边或者最右边的时候.我们就可以使用
requestDisallowInterceptTouchEvent(false).ViewPagerOut接到事件,开始滑动

重要结尾

最后引用一张最近发现的不错的图
作者:我是asha
链接http://www.jianshu.com/p/fe3d109eb27e
这里写图片描述

demo下载https://github.com/HumorSmith/TouchDemo.git

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值