Android Touch 事件分发感悟

本编意在指引入门,非技术性分析文章,以生活中的实例帮你更好的理解 touch 事件的传递。bash

回忆刚接触 touch 事件传递时,文章大可能是源码分析,对于有基础的人来讲,上手很容易,但对于我这种新手来讲,心中有万马奔腾。。。源码分析

其实事件的分发能够转换成咱们生活中的场景:

炎炎夏日,你和你爸爸都很热,如今在你爸爸手里有一根雪糕,那么这根雪糕怎么分、谁吃就能够演变成 Android touch 的事件分发。ui

咱们先说说结果,雪糕无非就三种,你吃、你爸爸吃、都不吃this

先说说你爸爸吃的状况:

  • 你爸爸不问你要不要,直接留下给本身,而后直接吃了。
  • 你爸爸问你要不要,你说不要,而后你爸爸吃了。

再说说你吃的状况:

  • 你爸爸问你要不要,你说要,你爸爸就给你吃了。
  • 你爸爸不问你要不要,可是你告诉你爸爸说你想吃,你爸爸虽然想吃,但仍是给你了。

最后都不吃的状况:

  • 你爸爸不吃,问你吃不吃,你也不吃,这时候就没人吃了。

上面这个场景应该很容易理解,那么换到 Android 的 touch 事件分发中,

  • 雪糕 = touch 事件,被封装成 MotionEvent 对象中。
  • 你爸爸 = ViewGroup,父 View,有 dispatchTouchEvent(拿到雪糕)、onInterceptTouchEvent(不问你,留下给本身)、onTouch(吃雪糕)三个方法。
  • 你 = View,子 View,有 dispatchTouchEvent(拿到雪糕)、onTouch(吃雪糕)两个方法。

经过这个场景,你们将方法带入,是否是就很容易理解了呢?spa

疑问一:为何子 View 没有 onInterceptTouchEvent 这个呢?

由于你已是最后一个了,不用问谁了,直接决定吃不吃就能够了。.net

疑问二:你吃里面的第二种状况,为何你爸爸都决定本身吃了,但为何只要你说你想吃,他就会给你呢?

其实你爸爸可否吃到雪糕的决定权仍是在你的手里,code

伪代码:对象

if( 孩子是否想吃 || !爸爸是否留下){
    给孩子吃
}else{
    爸爸吃
}
复制代码

默认孩子不想吃(false),爸爸不留下(false),blog

if( false || !false){
    给孩子吃
}else{
    爸爸吃
}
复制代码

正常的状况下都会给孩子吃, 当爸爸留下(true)时,事件

if( false || !true){
    给孩子吃
}else{
    爸爸吃
}
复制代码

就走到了 else 中,也就是爸爸吃。

在 Android 中咱们能够经过 requestDisallowInterceptTouchEvent(孩子是否想吃)这个方法改变孩子是否想吃的值,当孩子调用requestDisallowInterceptTouchEvent方法返回 true 时,不管爸爸是否想吃,都会走到孩子想吃中,也就是最终结果是你吃。

if( true || !爸爸是否留下){
    给孩子吃
}else{
    爸爸吃
}
复制代码

咱们的终极伪代码:

// 标记子 view 请求是否不拦截(孩子是否想吃,默认不想)
boolean disallowIntercept = false;
// 调用 dispatchTouchEvent(爸爸拿来了一根雪糕)
public boolean dispatchTouchEvent(MotionEvent ev) {
    // 标记事件是否被消费掉(雪糕是否被吃)
    boolean consume = false; 
    // 判断是否拦截事件(雪糕给不给孩子)
    if ( disallowIntercept || !onInterceptTouchEvent(ev)) {
      // 若拦截,则将该事件交给当前View进行处理
      // 即调用onTouchEvent 方法去处理点击事件(爸爸吃雪糕)
        consume = onTouchEvent (ev) ;
    } else {
      // 若不拦截,则将该事件传递到下层,即下层元素的dispatchTouchEvent就会被调用,直到点击事件被最终处理为止(孩子吃或者不吃)
      consume = child.dispatchTouchEvent (ev) ;
    }
    // 最终返回通知 该事件是否被消费(吃或不吃)
    return consume;
}
// 子 view 能够经过调用此方法 改变 disallowIntercept 的值
public void requestDisallowInterceptTouchEvent(boolean disallowIntercept){
    this.disallowIntercept = disallowIntercept;
}
复制代码

这里有几篇很是好的讲解:

相关文章
相关标签/搜索