• Android事件分发


    ViewGroup 分发-> 拦截 -> 处理  

    在事件分发的过程中,主要涉及到三个方法:

    • dispatchTouchEvent(MotionEvent event);

    • onInterceptTouchEvent(MotionEvent event);

    • onTouchEvent();

    分发处理流程:

    1、在dispatchTouchEvent中,先调用ViewGroup自身的onInterceptTouchEvent方法,判断自己是否要拦截。

    2、如果这时候自己拦截,那就调用自己的onTouchEvent方法,如果onTouchEvent方法返回了True,那么这次的事件就算消耗了,事件传递到此为止,,如果返回了False,证明这次没有消耗这次MotionEvent,那么这次的事件就会往上返回,由上一级继续处理。

    3、如果当前ViewGroup的onInterceptTouchEvent返回了False,那就会调用它的子view的dispatchTouchEvent方法,这样这个事件就传递下去了,如果它的子View处理不了,那么还会回来调用ViewGroup的onTouchEvent方法。

    View

      View不同于ViewGroup的是,View中没有onInterceptTouchEvent方法,因为View作为事件处理的最后一级,不需要判断是否要拦截,是一定要拦截,不管能不能处理,都要试一下,所以在View中调用流程是:dispatchTouchEvent -> onTouchEvent

    注意:

      view的enable状态和onTouchEvent是没有关系的,只有clickable状态是对onTouchEvent有影响的。

      设置 view的enable为false确实也会把view的clickable设成false,但是设置view的onclickListener就又把view的clickable变成了true,所以最后的解决方案就是把那两行代码换下先后顺序,问题就迎刃而解了。

    GesutureDetector处理事件

      GestureDetector是一个手势辅助检测类,默认能够检测多种手势:

    onTouchListener OnTouchEvent OnClickListener

      我们在知道onTouchEvent之前肯定都知道onClickListener和onTouchListener,而他们都是事件的消费者,onTouchListener是在onTouch方法中生效,而且onTouch要先于onTouchEvent,就是说一旦设置了onTouchListener并且最后onTouch方法返回了True,那onTouchEvent将不会再被执行,而onClickListener和onTouchEvent有些关系,onTouchEvent的默认实现里会调用onClickListener的onClick方法,如果重写了onTouchEvent,因为onClickListener接受不到ACTION_DOWN和ACTION_UP,那么再设置onClickListener也就不会再生效了,这个时候的单击或者长按处理只能在onTouchEvent中自己处理。

    结论:

    1、如果事件不被拦截,整个事件传递流向将呈U型状态。

      Activity---->ViewGroup--->View 从上往下调用dispatchTouchEvent方法,一直到叶子节点(View)的时候,再由View--->ViewGroup--->Activity从下往上调用onTouchEvent方法。

    2、dispatchTouchEvent 和 onTouchEvent 一旦return true,事件就停止传递了(到达终点)

    3、dispatchTouchEvent 和 onTouchEvent return false的时候事件都回传给父控件的onTouchEvent处理。

    4、dispatchTouchEvent、onTouchEvent、onInterceptTouchEvent
      ViewGroup 和View的这些方法的默认实现就是会让整个事件安装U型完整走完,所以 return super.xxxxxx() 就会让事件依照U型的方向的完整走完整个事件流动路径),中间不做任何改动,不回溯、不终止,每个环节都走到。

    总结:

    • 对于 dispatchTouchEvent,onTouchEvent,return true是终结事件传递。return false 是回溯到父View的onTouchEvent方法。
    • ViewGroup 想把自己分发给自己的onTouchEvent,需要拦截器onInterceptTouchEvent方法return true 把事件拦截下来。
    • ViewGroup 的拦截器onInterceptTouchEvent 默认是不拦截的,所以return super.onInterceptTouchEvent()=return false;
    • View 没有拦截器,为了让View可以把事件分发给自己的onTouchEvent,View的dispatchTouchEvent默认实现(super)就是把事件分发给自己的onTouchEvent。

      对于ACTION_MOVE、ACTION_UP总结:ACTION_DOWN事件在哪个控件消费了(return true), 那么ACTION_MOVE和ACTION_UP就会从上往下(通过dispatchTouchEvent)做事件分发往下传,就只会传到这个控件,不会继续往下传,如果ACTION_DOWN事件是在dispatchTouchEvent消费,那么事件到此为止停止传递,如果ACTION_DOWN事件是在onTouchEvent消费的,那么会把ACTION_MOVE或ACTION_UP事件传给该控件的onTouchEvent处理并结束传递。

  • 相关阅读:
    spring jdbcTemplate使用queryForList示例
    凡事预则立,不立则废:好计划是成功的开始——布利斯定理
    传世智库:初识IPD-集成产品开发
    骑手送外卖获奖1500多万元又被撤销 法律专家:不能一扣了之
    leetcode-----129. 求根到叶子节点数字之和
    leetcode-----128. 最长连续序列
    leetcode-----127. 单词接龙
    leetcode-----126. 单词接龙 II
    leetcode-----125. 验证回文串
    leetcode-----124. 二叉树中的最大路径和
  • 原文地址:https://www.cnblogs.com/yl-saber/p/7115857.html
Copyright © 2020-2023  润新知