`
weihe6666
  • 浏览: 430226 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

ViewGroup onInterceptTouchEvent and OnTouchEvent

阅读更多

ViewGroup 继承View,实现了View各个方法,同时ViewGroup中包含了不同的View,事件消息在ViewGroup中的传递就比较重要了,理解了事件的传递,才能够写出符合需求的自定义的ViewGroup。

首先分析一下onInterceptTouchEvent函数,此函数是ViewGroup独有的拦截函数,顾名思义,是拦截用户触发的事件,来决定此事件是否要传递给子View。原理比较简单,但是传递流程稍许复杂。

先看一段官方的文档:

·  You will receive the down event here.
·  The down event will be handled either by a child of this view group, or given to your own onTouchEvent() method to handle; this means you should implement onTouchEvent() to return true, so you will continue to see the rest of the gesture (instead of looking for a parent view to handle it). Also, by returning true from onTouchEvent(), you will not receive any following events in onInterceptTouchEvent() and all touch processing must happen in onTouchEvent() like normal.
·  For as long as you return false from this function, each following event (up to and including the final up) will be delivered first here and then to the target's onTouchEvent().
·  If you return true from here, you will not receive any following events: the target view will receive the same event but with the action ACTION_CANCEL, and all further events will be delivered to your onTouchEvent() method and no longer appear here.

看着头昏脑涨,在来一段中文的翻译:
由于onInterceptTouchEvent()的机制比较复杂,上面的说明写的也比较复杂,总结一下,基本的规则是:
1.       down事件首先会传递到onInterceptTouchEvent()方法
2.       如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return false,那么后续的move, up等事件将继续会先传递给该ViewGroup,之后才和down事件一样传递给最终的目标view的onTouchEvent()处理。
3.       如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return true,那么后续的move, up等事件将不再传递给onInterceptTouchEvent(),而是和down事件一样传递给该ViewGroup的onTouchEvent()处理,注意,目标view将接收不到任何事件。
4.       如果最终需要处理事件的view的onTouchEvent()返回了false,那么该事件将被传递至其上一层次的view的onTouchEvent()处理。
5.       如果最终需要处理事件的view 的onTouchEvent()返回了true,那么后续事件将可以继续传递给该view的onTouchEvent()处理。

这里重要一点是对down事件的处理,这里是决定消息是分发给子View还是自己处理的关键点。


demo1: layout以及子View onTouchEvent 返回true

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
       int action = ev.getAction();
       switch(action){
       case MotionEvent.ACTION_DOWN:
           Log.d(TAG,"onInterceptTouchEvent action:ACTION_DOWN");
//           break;
           return true;
       case MotionEvent.ACTION_MOVE:
           Log.d(TAG,"onInterceptTouchEvent action:ACTION_MOVE");
           break;
//           return true;
       case MotionEvent.ACTION_UP:
           Log.d(TAG,"onInterceptTouchEvent action:ACTION_UP");
           break;
//           return true;
       case MotionEvent.ACTION_CANCEL:
           Log.d(TAG,"onInterceptTouchEvent action:ACTION_CANCEL");
           break;
          
       }
       return false;
    }

在layout中拦截ACTION_DOWN,子类view不会收到任何消息,而是直接把消息分发给layout的OnToucheEvent处理

D/LayoutView2(15426): onInterceptTouchEvent action:ACTION_DOWN
D/LayoutView2(15426): onTouchEvent action:ACTION_DOWN
D/LayoutView2(15426): onTouchEvent action:ACTION_MOVE
D/LayoutView2(15426): onTouchEvent action:ACTION_MOVE
D/LayoutView2(15426): onTouchEvent action:ACTION_MOVE
D/LayoutView2(15426): onTouchEvent action:ACTION_MOVE
D/LayoutView2(15426): onTouchEvent action:ACTION_MOVE
D/LayoutView2(15426): onTouchEvent action:ACTION_MOVE
D/LayoutView2(15426): onTouchEvent action:ACTION_UP


Demo2:layout 拦截ACTION_MOVE  layout以及子View onTouchEvent 返回true
    public boolean onInterceptTouchEvent(MotionEvent ev) {
       int action = ev.getAction();
       switch(action){
       case MotionEvent.ACTION_DOWN:
           Log.d(TAG,"onInterceptTouchEvent action:ACTION_DOWN");
           break;
//           return true;
       case MotionEvent.ACTION_MOVE:
           Log.d(TAG,"onInterceptTouchEvent action:ACTION_MOVE");
//           break;
           return true;
       case MotionEvent.ACTION_UP:
           Log.d(TAG,"onInterceptTouchEvent action:ACTION_UP");
           break;
//           return true;
       case MotionEvent.ACTION_CANCEL:
           Log.d(TAG,"onInterceptTouchEvent action:ACTION_CANCEL");
           break;
          
       }
       return false;
    }
layout的消息传递:
D/LayoutView2(15765): onInterceptTouchEvent action:ACTION_DOWN
D/LayoutView2(15765): onInterceptTouchEvent action:ACTION_MOVE
D/LayoutView2(15765): onTouchEvent action:ACTION_MOVE
D/LayoutView2(15765): onTouchEvent action:ACTION_UP

也就是当 action:ACTION_MOVE被拦截时,action:ACTION_MOVE后续的消息直接传递给onTouchEvent

子View的消息传递为:
D/MyTextView(15765): onTouchEvent action:ACTION_DOWN
D/MyTextView(15765): onTouchEvent action:ACTION_CANCEL (这个消息一直没有弄明白)


Demo3:layout 拦截ACTION_MOVE  layout onTouchEvent 返回true 子View的onTouchEvent返回false

    public boolean onInterceptTouchEvent(MotionEvent ev) {
       int action = ev.getAction();
       switch(action){
       case MotionEvent.ACTION_DOWN:
           Log.d(TAG,"onInterceptTouchEvent action:ACTION_DOWN");
           break;
//           return true;
       case MotionEvent.ACTION_MOVE:
           Log.d(TAG,"onInterceptTouchEvent action:ACTION_MOVE");
           break;
//           return true;
       case MotionEvent.ACTION_UP:
           Log.d(TAG,"onInterceptTouchEvent action:ACTION_UP");
           break;
//           return true;
       case MotionEvent.ACTION_CANCEL:
           Log.d(TAG,"onInterceptTouchEvent action:ACTION_CANCEL");
           break;
          
       }
       return false;
    }


layout的消息传递:

D/LayoutView2(16536): onInterceptTouchEvent action:ACTION_DOWN
D/LayoutView2(16536): onTouchEvent action:ACTION_DOWN
D/LayoutView2(16536): onTouchEvent action:ACTION_MOVE
D/LayoutView2(16536): onTouchEvent action:ACTION_UP

子View消息传递:
D/MyTextView(16536): onTouchEvent action:ACTION_DOWN



这里消息向下拦截的逻辑,当onInterceptTouchEvent拦截了ACTION_MOVE后,ACTION_MOVE后的消息就不在分发给子View,而是分发给layout的OnTouchEvent。

如果Layout的onInterceptTouchEvent对ACTION_DOWN消息没有拦截,但是子View的OntouchEvent不处理这些消息,仍会返回Layout的OnTouchEvent,如果Layout的OnTouchEvent对ACTION_DOWN消息进行了处理,后续的消息就会直接发送到Layout的OnTouchEvent。

分享到:
评论

相关推荐

    自定义控件代码

    侧滑面板(对ViewGroup的自定义) * 应用场景: 扩展主面板的功能 ... 触摸优化: 重写ViewGroup里onInterceptTouchEvent和onTouchEvent Github 大牛 Jake Wharton nineoldandroids.jar 属性动画 ActionBarSherlock

    ViewDragHelper完全解析 自定义ViewGroup神器

    在自定义ViewGroup中,很多效果都包含用户手指去拖动其内部的某个View(eg:侧滑菜单等),针对具体的需要去写好onInterceptTouchEvent和onTouchEvent这两个方法是一件很不容易的事,需要自己去处理:多手指的处理、加...

    android事件分发机制测试demo

    安卓事件分发机制测试代码,事件传递从Activity-->ViewGroup-->View。dispatchTouchEvent,onInterceptTouchEvent,onTouchEvent这三个函数的返回值不同,代表的事件传递的不同。

    Android应用开发中自定义ViewGroup的究极攻略

    最近在学习android的view部分,于是动手实现了一个类似ViewPager的可上下或者左右拖动的ViewGroup,中间遇到了一些问题(例如touchEvent在onInterceptTouchEvent和onTouchEvent之间的传递流程),现在将我的实现过程...

    Android ViewDragHelper完全解析 自定义ViewGroup神器

    在自定义ViewGroup中,很多效果都包含用户手指去拖动其内部的某个View(eg:侧滑菜单等),针对具体的需要去写好onInterceptTouchEvent和onTouchEvent这两个方法是一件很不容易的事,需要自己去处理:多手指的处理、加...

    Android 事件分发详解及示例代码

    Android中与事件分发相关的方法主要包括dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent三个方法,而事件分发一般会经过三种容器,分别为Activity、ViewGroup、View。下表对这三种容器分别拥有的事件分发...

    Android事件分发小结

    事件传递方法包括dispatchTouchEvent、onTouchEvent、onInterceptTouchEvent,其中前两个是View和ViewGroup都有的,最后一个是只有ViewGroup才有的方法。这三个方法的作用分别是负责事件分发、事件处理、事件拦截。 ...

    完全理解android事件分发机制

    在View中其间会调用onTouchEvent(),在ViewGroup中其间会调用onInterceptTouchEvent()和onTouchEvent()。 **onInterceptTouchEvent():**这个函数是事件拦截函数,是ViewGroup才有的函数。

    事件机制测试Demo

    android系统中的每个ViewGroup的子类都具有下面三个和TouchEvent处理密切相关的方法: 1)public boolean dispatchTouchEvent(MotionEvent ev) 这个方法用来分发TouchEvent 2)public boolean ...

    Android listview的滑动冲突解决方法

    Android listview的滑动冲突解决方法 ...一般来说,view的onTouchEvent返回true,即消耗点击事件,viewgroup的onInterceptTouchEvent返回false,即不拦截点击事件,这一点从android源码中可以看出来。但是lis

    30分钟搞清楚Android Touch事件分发机制

    Touch事件分发中只有两个主角:...ViewGroup的相关事件有三个:onInterceptTouchEvent、dispatchTouchEvent、onTouchEvent。View的相关事件只有两个:dispatchTouchEvent、onTouchEvent。 先分析ViewGroup的处理流程

    安卓touch事件的分发和消费机制

    Android中与Touch事件相关的方法包括:dispatchTouchEvent(MotionEvent ev)、onInterceptTouchEvent(MotionEvent ev)、onTouchEvent(MotionEvent ev);能够响应这些方法的控件包括:ViewGroup、View、Activity。继承...

    Android 编程下 Touch 事件的分发和消费机制

    Android 中与 Touch 事件相关的方法包括:dispatchTouchEvent(MotionEvent ev)、onInterceptTouchEvent(MotionEvent ev)、onTouchEvent(MotionEvent ev);能够响应这些方法的控件包括:ViewGroup、View、Activity。...

    Android 事件分发机制 讲解

    1、分发事件的组件 ...onInterceptTouchEvent() onTouchListener(); onTouchEvent() 3、事件流程图(Action Down) 注意:Action Move和Action Up流程和上图是有区别的 4、嵌套滑动 如果需要实现嵌套

    Android View 事件分发机制详解

    Android开发,触控无处不在。...说白了这些触控的事件分发机制就是弄清楚三个方法,dispatchTouchEvent(),OnInterceptTouchEvent(),onTouchEvent(),和这三个方法与n个ViewGroup和View堆叠在一起的问题,再复杂的

    Android仿微信列表滑动删除 如何实现滑动列表SwipeListView

    接上一篇,本篇主要讲如何实现滑动...当然啦,这个SwipeListView继承自ListView,为了实现我们需要的功能,重点就是重写ListView的onTouchEvent()以及onInterceptTouchEvent()这个方法了。先说onTouchEvent(): @Over

    DragVideo,一种在播放视频时,可以任意拖拽的方案

    ViewDragHelper的本质其实是分析onInterceptTouchEvent和onTouchEvent的MotionEvent参数,然后根据分析的结果去改变一个容器中被拖动子View的位置( 通过offsetTopAndBottom(int offset)和offsetLeftAndRight(int ...

    Android View的事件分发机制

    2、事件的拦截机制,onInterceptTouchEvent。主要是parent根据它内部的状态、或者child的状态,来把事件拦截下来,阻止其进一步传递到child的机制。 3、事件的处理机制,onTouchEvent。主要是事件序列的接受者(可以...

    TouchEvent:关于Touch事件的几个模拟示例.如果对分发机制不是很了解的,又没有太多时间模拟实验的,可以参考

    Touch模拟实例 关于Touch事件的几个模拟示例.如果对分发机制不是很了解的,又没有太多时间模拟实验的,可以参考. 原流程 例子有3个控件: GrandparentView extends ViewGroup ...GrandparentView onTouchEvent ACTION_DO

Global site tag (gtag.js) - Google Analytics