onInterceptTouchEvent和onTouchEvent调用时序

Camunda 7.x 系列【22】全局监听器 Camunda支持义一个全局ExecutionListener和一个全局TaskListener,会捕获流程中发生的所有事件的通知,这样可以定义一个全局的审批人检查监听器,作用于所有用户任务。 阅读详情

转载自:http://blog.youkuaiyun.com/ddna/article/details/5473293


onInterceptTouchEvent和onTouchEvent调用时序

onInterceptTouchEvent()是ViewGroup的一个方法,目的是在系统向该ViewGroup及其各个childView触发onTouchEvent()之前对相关事件进行一次拦截,Android这么设计的想法也很好理解,由于ViewGroup会包含若干childView,因此需要能够统一监控各种touch事件的机会,因此纯粹的不能包含子view的控件是没有这个方法的,如LinearLayout就有,TextView就没有。 

onInterceptTouchEvent()使用也很简单,如果在ViewGroup里覆写了该方法,那么就可以对各种touch事件加以拦截。但是如何拦截,是否所有的touch事件都需要拦截则是比较复杂的,touch事件在onInterceptTouchEvent()和onTouchEvent以及各个childView间的传递机制完全取决于onInterceptTouchEvent()和onTouchEvent()的返回值。并且,针对down事件处理的返回值直接影响到后续move和up事件的接收和传递。 

关于返回值的问题,基本规则很清楚,如果return true,那么表示该方法消费了此次事件,如果return false,那么表示该方法并未处理完全,该事件仍然需要以某种方式传递下去继续等待处理。

SDK给出的说明如下:

·  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()处理。

 

下面用一个简单的实验说明上述复杂的规则。视图自底向上共3层,其中LayoutView1和LayoutView2就是LinearLayout, MyTextView就是TextView:

对应的xml布局文件如下:

<?xml version="1.0" encoding="utf-8"?>

<com.touchstudy.LayoutView1 xmlns:android="http://schemas.android.com/apk/res/android"

    android:orientation="vertical"

    android:layout_width="fill_parent"

    android:layout_height="fill_parent" >

    <com.touchstudy.LayoutView2

        android:orientation="vertical"

        android:layout_width="fill_parent"

        android:layout_height="fill_parent"

        android:gravity="center">

       <com.touchstudy.MyTextView 

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:id="@+id/tv"

            android:text="AB"

            android:textSize="40sp"

            android:textStyle="bold"

            android:background="#FFFFFF"

            android:textColor="#0000FF"/>

   </com.touchstudy.LayoutView2>

</com.touchstudy.LayoutView1>

 

下面看具体情况:

1.       onInterceptTouchEvent()处理down事件均返回false,onTouchEvent()处理事件均返回true

------------------------------------------------------------------------------------------------------------------------------

04-11 03:58:42.620: DEBUG/LayoutView1(614): onInterceptTouchEvent action:ACTION_DOWN

04-11 03:58:42.620: DEBUG/LayoutView2(614): onInterceptTouchEvent action:ACTION_DOWN

04-11 03:58:42.620: DEBUG/MyTextView(614): onTouchEvent action:ACTION_DOWN

04-11 03:58:42.800: DEBUG/LayoutView1(614): onInterceptTouchEvent action:ACTION_MOVE

04-11 03:58:42.800: DEBUG/LayoutView2(614): onInterceptTouchEvent action:ACTION_MOVE

04-11 03:58:42.800: DEBUG/MyTextView(614): onTouchEvent action:ACTION_MOVE

…… //省略过多的ACTION_MOVE

04-11 03:58:43.130: DEBUG/LayoutView1(614): onInterceptTouchEvent action:ACTION_UP

04-11 03:58:43.130: DEBUG/LayoutView2(614): onInterceptTouchEvent action:ACTION_UP

04-11 03:58:43.150: DEBUG/MyTextView(614): onTouchEvent action:ACTION_UP

------------------------------------------------------------------------------------------------------------------------------

这是最常见的情况,onInterceptTouchEvent并没有做任何改变事件传递时序的操作,效果上和没有覆写该方法是一样的。可以看到,各种事件的传递本身是自底向上的,次序是:LayoutView1->LayoutView2->MyTextView。注意,在onInterceptTouchEvent均返回false时,LayoutView1和LayoutView2的onTouchEvent并不会收到事件,而是最终传递给了MyTextView。

 

2.     LayoutView1的onInterceptTouchEvent()处理down事件返回true,

MyTextView的onTouchEvent()处理事件返回true

------------------------------------------------------------------------------------------------------------------------------

04-11 03:09:27.589: DEBUG/LayoutView1(446): onInterceptTouchEvent action:ACTION_DOWN

04-11 03:09:27.589: DEBUG/LayoutView1(446): onTouchEvent action:ACTION_DOWN

04-11 03:09:27.629: DEBUG/LayoutView1(446): onTouchEvent action:ACTION_MOVE

04-11 03:09:27.689: DEBUG/LayoutView1(446): onTouchEvent action:ACTION_MOVE

…… //省略过多的ACTION_MOVE

04-11 03:09:27.959: DEBUG/LayoutView1(446): onTouchEvent action:ACTION_UP

------------------------------------------------------------------------------------------------------------------------------

从Log可以看到,由于LayoutView1在拦截第一次down事件时return true,所以后续的事件(包括第一次的down)将由LayoutView1本身处理,事件不再传递下去。

 

3.       LayoutView1,LayoutView2的onInterceptTouchEvent()处理down事件返回false,

MyTextView的onTouchEvent()处理事件返回false

LayoutView2的onTouchEvent()处理事件返回true

----------------------------------------------------------------------------------------------------------------------------

04-11 09:50:21.147: DEBUG/LayoutView1(301): onInterceptTouchEvent action:ACTION_DOWN

04-11 09:50:21.147: DEBUG/LayoutView2(301): onInterceptTouchEvent action:ACTION_DOWN

04-11 09:50:21.147: DEBUG/MyTextView(301): onTouchEvent action:ACTION_DOWN

04-11 09:50:21.147: DEBUG/LayoutView2(301): onTouchEvent action:ACTION_DOWN

04-11 09:50:21.176: DEBUG/LayoutView1(301): onInterceptTouchEvent action:ACTION_MOVE

04-11 09:50:21.176: DEBUG/LayoutView2(301): onTouchEvent action:ACTION_MOVE

04-11 09:50:21.206: DEBUG/LayoutView1(301): onInterceptTouchEvent action:ACTION_MOVE

04-11 09:50:21.217: DEBUG/LayoutView2(301): onTouchEvent action:ACTION_MOVE

…… //省略过多的ACTION_MOVE

04-11 09:50:21.486: DEBUG/LayoutView1(301): onInterceptTouchEvent action:ACTION_UP

04-11 09:50:21.486: DEBUG/LayoutView2(301): onTouchEvent action:ACTION_UP

----------------------------------------------------------------------------------------------------------------------------

可以看到,由于MyTextView在onTouchEvent()中return false,down事件被传递给其父view,即LayoutView2的onTouchEvent()方法处理,由于在LayoutView2的onTouchEvent()中return true,所以down事件传递并没有上传到LayoutView1。注意,后续的move和up事件均被传递给LayoutView2的onTouchEvent()处理,而没有传递给MyTextView。

 

----------------------------------------------------------------------------------------------------------------

应大家的要求,我把源代码贴上,其实很简单,就是基础文件,主要是用来观察事件的传递。

 

主Activity: InterceptTouchStudyActivity.java:

 

public class InterceptTouchStudyActivity extends Activity {

    static final String TAG = "ITSActivity";

    TextView tv;

   

    /** Called when the activity is first created. */

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.layers_touch_pass_test);

     }

 }

 


      LayoutView1.java:


      public class LayoutView1 extends LinearLayout {

      private final String TAG = "LayoutView1";

        public LayoutView1(Context context, AttributeSet attrs) {

         super(context, attrs);

         Log.d(TAG,TAG);

     }

 

     @Override

     public boolean onInterceptTouchEvent(MotionEvent ev) {

         int action = ev.getAction();

         switch(action){

         case MotionEvent.ACTION_DOWN:

              Log.d(TAG,"onInterceptTouchEvent action:ACTION_DOWN");

//            return true;

              break;

         case MotionEvent.ACTION_MOVE:

              Log.d(TAG,"onInterceptTouchEvent action:ACTION_MOVE");

              break;

         case MotionEvent.ACTION_UP:

              Log.d(TAG,"onInterceptTouchEvent action:ACTION_UP");

              break;

         case MotionEvent.ACTION_CANCEL:

              Log.d(TAG,"onInterceptTouchEvent action:ACTION_CANCEL");

              break;

         }

        

         return false;

     }

 

     @Override

     public boolean onTouchEvent(MotionEvent ev) {

         int action = ev.getAction();

         switch(action){

         case MotionEvent.ACTION_DOWN:

              Log.d(TAG,"onTouchEvent action:ACTION_DOWN");

              break;

         case MotionEvent.ACTION_MOVE:

              Log.d(TAG,"onTouchEvent action:ACTION_MOVE");

              break;

         case MotionEvent.ACTION_UP:

              Log.d(TAG,"onTouchEvent action:ACTION_UP");

              break;

         case MotionEvent.ACTION_CANCEL:

              Log.d(TAG,"onTouchEvent action:ACTION_CANCEL");

              break;

         }

        

         return true;

     }

 

     @Override

     protected void onLayout(boolean changed, int l, int t, int r, int b) {

         // TODO Auto-generated method stub

         super.onLayout(changed, l, t, r, b);

     }

 

     @Override

     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

         // TODO Auto-generated method stub

         super.onMeasure(widthMeasureSpec, heightMeasureSpec);

     }

}


LayoutView2.java:

 

public class LayoutView2 extends LinearLayout {

    private final String TAG = "LayoutView2";

   

    public LayoutView2(Context context, AttributeSet attrs) {

       super(context, attrs);

       Log.d(TAG,TAG);

    }

 

    @Override

    public boolean onInterceptTouchEvent(MotionEvent ev) {

       int action = ev.getAction();

       switch(action){

       case MotionEvent.ACTION_DOWN:

           Log.d(TAG,"onInterceptTouchEvent action:ACTION_DOWN");

           break;

       case MotionEvent.ACTION_MOVE:

           Log.d(TAG,"onInterceptTouchEvent action:ACTION_MOVE");

           break;

       case MotionEvent.ACTION_UP:

           Log.d(TAG,"onInterceptTouchEvent action:ACTION_UP");

           break;

       case MotionEvent.ACTION_CANCEL:

           Log.d(TAG,"onInterceptTouchEvent action:ACTION_CANCEL");

           break;

       }

      

       return false;

    }

 

    @Override

    public boolean onTouchEvent(MotionEvent ev) {

       int action = ev.getAction();

       switch(action){

       case MotionEvent.ACTION_DOWN:

           Log.d(TAG,"onTouchEvent action:ACTION_DOWN");

           break;

       case MotionEvent.ACTION_MOVE:

           Log.d(TAG,"onTouchEvent action:ACTION_MOVE");

           break;

       case MotionEvent.ACTION_UP:

           Log.d(TAG,"onTouchEvent action:ACTION_UP");

           break;

       case MotionEvent.ACTION_CANCEL:

           Log.d(TAG,"onTouchEvent action:ACTION_CANCEL");

           break;

       }

      

       return true;

    } 

}


MyTextView.java:

public class MyTextView extends TextView {

    private final String TAG = "MyTextView";

   

    public MyTextView(Context context, AttributeSet attrs) {

       super(context, attrs);

       Log.d(TAG,TAG);

    }

 

    @Override

    public boolean onTouchEvent(MotionEvent ev) {

       int action = ev.getAction();

       switch(action){

       case MotionEvent.ACTION_DOWN:

           Log.d(TAG,"onTouchEvent action:ACTION_DOWN");

           break;

       case MotionEvent.ACTION_MOVE:

           Log.d(TAG,"onTouchEvent action:ACTION_MOVE");

           break;

       case MotionEvent.ACTION_UP:

           Log.d(TAG,"onTouchEvent action:ACTION_UP");

           break;

       case MotionEvent.ACTION_CANCEL:

           Log.d(TAG,"onTouchEvent action:ACTION_CANCEL");

           break;

       }

      

       return false;

    }

   

    public void onClick(View v) {

       Log.d(TAG, "onClick");

    }

   

    public boolean onLongClick(View v) {

       Log.d(TAG, "onLongClick");

       return false;

    }

}


//===============================================分割线==============================
感谢原作者,总结的非常好!疑惑好久的问题终于拨开迷雾见真知了。
这里我再简单的总结下:
就是touch事件传递是这样的:分两步来传递,第一步是走ViewGroup的oninterceptTouchEvent()方法,来进行事件的拦截(不是消耗事件),是从下向上来进行拦截的,就是从最底层的ViewGroup开始拦截如果返回false证明没有拦截,那么就将事件传递到它上层的ViewGoup,依次类推直到最上面的View;第二步,是走ViewGroup或者View的onTouchEvent()方法来进行事件的消费,是从上向下消费的。
下面详细说说这两个步骤的细节:
在事件传递和消费过程中,关键就是要看Event.ACTION_DOWN 这个事件,①在事件传递过程中(ViewGroup执行oninterceptTouchEvent()方法的过程中)如果在Event.ACTION_DOWN事件中返回了true,那么当前ViewGroup就拦截了事件传递,就会转而执行ViewGroup中的onTouchEvent()方法,事件就到此不会再向下传递了(并且当前ViewGroup的 oninterceptTouchEvent()方法中除了 Event.ACTION_DOWN 事件会执行外,其它的事件都不会执行了直到此次touch事件结束);②在事件消费过程中,事件消费是从上往下走的,假如最上层的View能够接收到touch事件,并且在onTouchEvent()方法中消费了事件(return true)那么事件就不会再向下传递了。



辐射制冷无规散射结构非球形散射体的结构优化与设计准则 本文针对辐射制冷材料中非球形散射体的光散射特性开展研究,提出了一种基于体积散射截面和不对称因子的综合评价方法。通过建立简化模型分析球体、圆柱体、长方体等六种几何形状在太阳波段的散射性能,发现金字塔形和圆锥形具有更强的后向散射能力。研究创新性地提出"反射因子SR=S(1-g)"这一评价参数,该参数与宏观反射率高度相关,为非球形散射体的优化设计提供了定量依据。仿真结果表明,合理选择散射体形状可显著提升辐射制冷材料的太阳反射率,为实现高效被动制冷提供了新的结构设计思路。 阅读详情

相关推荐

从零开始:在CentOS服务器上部署R Shiny应用的完整指南

本文提供了一份在CentOS服务器上部署R Shiny应用的完整实战指南。内容涵盖从创建专用用户、安装R语言环境、配置Shiny Server,到最终部署应用并配置防火墙的全过程。针对部署过程中常见的权限、端口及依赖问题,给出了详细的解决方案,旨在帮助数据分析师和开发者将本地Shiny应用稳定、安全地发布至生产环境。

weixin_29079743的博客 135

Android-onInterceptTouchEvent()和onTouchEvent()总结

老实说,这两个小东东实在是太麻烦了,很不好懂,我自己那api文档都头晕,在网上找到很多资料,才知道是怎么回事,这里总结一下,记住这个原则就会很清楚了: 1、onInterceptTouchEvent()是用于处理事件(类似于预处理,当然也可以不处理)并改变事件的传递方向,也就是决定是否允许Touch事件继续向下(子控件)传递,一但返回True(代表事件在当前的viewGroup中会被处理),则向...

LVXIANGAN的专栏 6万+

无线图像传输新突破:深度JSCC算法在低带宽环境下的性能实测

本文深入探讨了基于深度学习的信源信道联合编码(JSCC)算法在低带宽无线图像传输中的突破性表现。通过实测数据对比,深度JSCC在低信噪比环境下展现出卓越的鲁棒性,有效对抗传统方案的“悬崖效应”,实现图像质量的平滑下降,为远程医疗、工业巡检等严苛场景提供了新的解决方案。

weixin_29090089的博客 504

关于Android事件分发中onInterceptTouchEvent调用时机

首先,当一个down事件来临的时候,viewgroup的dispachTouchEvent中会清除所有的上一个手势的状态 // Handle an initial down. if (actionMasked == MotionEvent.ACTION_DOWN) { // Throw away all previous state when starting a new touch

u011424451的专栏 3681

电商智能客服Agent开发实战:从零到一构建企业级AI助手

电商智能客服Agent是下一代AI应用的核心形态,它不仅能够回答用户问题,还能自主规划任务、调用工具并执行完整工作流程。本文将深入探讨AI Agent的基本概念、技术实现方式及电商场景中的应用,提供完整的开发流程和代码示例,帮助开发者从零开始构建一个功能强大的电商智能客服系统。通过模块化设计、多轮对话记忆管理和工具集成,这个Agent能够处理订单查询、商品推荐、退换货流程等复杂任务,同时具备企业级的安全性和稳定性保障。通过本文的介绍,读者已经掌握了构建电商智能客服Agent的核心技术与实现方法。

m0_64363449的博客 1360

极化码理论及算法研究6-SCL、CA-SCL及matlab仿真

极化码译码算法5——SCL/CA-SCL译码算法系列目录1、引言2、串行抵消列表(SCL)译码算法2.1、路径度量PM 系列目录 (如要找其他内容,欢迎访问我的主页寻找) #前言 #极化码概述 #极化码定义 #极化码编码 #极化码译码 #5G标准中极化码的编译码概述 #5G标准中极化码的编码 #5G标准中极化码的译码 #总结 1、引言 在上一节中,介绍了经典的SC译码算法的理论原理以及其matlab仿真代码,SC译码算法具有较低的译码复杂度,但是由于每个译码的比特信息都依赖于前面所有的比特信息的译码结果,得

1万+

Android中onInterceptTouchEvent和onTouchEvent调用时序

重写viewGroup的时候经常会用到的方法,文章对该段API进行了翻译,例子就不转了,可以去看原文,主要存留下翻译的这段文字和原作者自己的理解,对深入了解该机制有一定的帮助! 原文地址:http://www.blogjava.net/TiGERTiAN/archive/2011/02/22/344869.html   onInterceptTouchEvent()是ViewGroup的一个

Mr梵谷的专栏 3163

CiteSpace基础操作(CNKI数据的导入分析)(一)

1 Cite Space简单介绍 2 文献导入 2.1 打开知网,选择高级检索

m0_50990607的博客 5万+
上一篇: android 中的Style、Themes以及attr
下一篇: <转>Android ListAdapter的高级功能
恶魔果实
博客等级 码龄15年 6粉丝 13原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值