尊重原创:http://blog.csdn.net/yuanzeyao/article/details/38025165

资源下载:http://download.csdn.net/detail/yuanzeyao2008/7660997

在前一篇文章中,我主要讲解了Android源码中的Touch事件的传递过程,现在我想使用一个demo以及一个实例来学习一下Andorid中的Touch事件处理过程。

在Android系统中,和Touch事件分发和处理紧密相关的三个函数如下:
(1) public boolean dispatchTouchEvent(MotionEvent ev)
(2) public boolean onInterceptTouchEvent(MotionEvent ev)
(3) public boolean onTouchEvent(MotionEvent event)

这三个方法我在前一篇文章中都对他们的源码进行了分析:方法1主要是对Touch事件进行分发,方法2主要是对Touch事件进行拦截,方法3是对Touch事件进行处理

这三个方法主要存在于ViewGroup,View,Activity中,具体情况如下图:

 

ViewGroup

View

Activity

dispatchTouchEvent

onInterceptTouchEvent

onTouchEvent

下面我们就使用一个demo来看看这些方法的执行流程:
自定义一个类:MyLayoutFirst.java

  1. public class MyLayoutFirst extends LinearLayout
  2. {
  3. private static final String TAG = "MyLayoutFirst";
  4. public MyLayoutFirst(Context context, AttributeSet attrs)
  5. {
  6. super(context, attrs);
  7. }
  8. @Override
  9. public boolean onInterceptTouchEvent(MotionEvent ev)
  10. {
  11. Log.w("yzy", "MyLayoutFirst->onInterceptTouchEvent->"+MyUtils.getActionName(ev));
  12. return super.onInterceptTouchEvent(ev);
  13. }
  14. @Override
  15. public boolean onTouchEvent(MotionEvent event)
  16. {
  17. Log.e("yzy", "MyLayoutFirst->onTouchEvent->"+MyUtils.getActionName(event));
  18. return super.onTouchEvent(event);
  19. }
  20. @Override
  21. public boolean dispatchTouchEvent(MotionEvent ev)
  22. {
  23. Log.i("yzy", "MyLayoutFirst->dispatchTouchEvent->"+MyUtils.getActionName(ev));
  24. return super.dispatchTouchEvent(ev);
  25. }
  26. }

自定义一个类;MyLayoutSecond.java

  1. public class MyLayoutSecond extends LinearLayout
  2. {
  3. private static final String TAG = "MyLayoutSecond";
  4. public MyLayoutSecond(Context context, AttributeSet attrs)
  5. {
  6. super(context, attrs);
  7. }
  8. @Override
  9. public boolean onTouchEvent(MotionEvent event)
  10. {
  11. Log.e("yzy", "MyLayoutSecond->MyLayoutSecond->"+MyUtils.getActionName(event));
  12. return super.onTouchEvent(event);
  13. }
  14. @Override
  15. public boolean onInterceptTouchEvent(MotionEvent ev)
  16. {
  17. Log.w("yzy", "MyLayoutSecond->onInterceptTouchEvent->"+MyUtils.getActionName(ev));
  18. return super.onInterceptTouchEvent(ev);
  19. }
  20. @Override
  21. public boolean dispatchTouchEvent(MotionEvent ev)
  22. {
  23. Log.i("yzy", "MyLayoutSecond->dispatchTouchEvent->"+MyUtils.getActionName(ev));
  24. return super.dispatchTouchEvent(ev);
  25. }
  26. }

加入到main_layout.xml中

  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. >
  6. <com.event.demo.MyLayoutFirst
  7. android:id="@+id/layout_first"
  8. android:layout_width="match_parent"
  9. android:layout_height="match_parent"
  10. android:background="#FF0000"
  11. >
  12. <com.event.demo.MyLayoutSecond
  13. android:id="@+id/layout_second"
  14. android:layout_width="320dip"
  15. android:layout_height="120dip"
  16. android:layout_gravity="center"
  17. android:background="#0000FF"
  18. >
  19. </com.event.demo.MyLayoutSecond>
  20. </com.event.demo.MyLayoutFirst>
  21. </RelativeLayout>

MainActivity中加入onTouchEvent方法

  1. public class MainActivity extends Activity
  2. {
  3. @Override
  4. protected void onCreate(Bundle savedInstanceState)
  5. {
  6. super.onCreate(savedInstanceState);
  7. setContentView(R.layout.activity_main);
  8. }
  9. @Override
  10. public boolean onCreateOptionsMenu(Menu menu)
  11. {
  12. // Inflate the menu; this adds items to the action bar if it is present.
  13. getMenuInflater().inflate(R.menu.main, menu);
  14. return true;
  15. }
  16. @Override
  17. public boolean dispatchTouchEvent(MotionEvent ev)
  18. {
  19. Log.i("yzy", "MainActivity->dispatchTouchEvent->"+MyUtils.getActionName(ev));
  20. return super.dispatchTouchEvent(ev);
  21. }
  22. @Override
  23. public boolean onTouchEvent(MotionEvent event)
  24. {
  25. Log.e("yzy", "MainActivity->onTouchEvent->"+MyUtils.getActionName(event));
  26. return super.onTouchEvent(event);
  27. }
  28. }

最后就一个工具类,用来将事件id转换为字符串。

  1. public class MyUtils
  2. {
  3. private static final String TAG = "MyUtils";
  4. public static String getActionName(MotionEvent event)
  5. {
  6. String name="";
  7. switch(event.getAction())
  8. {
  9. case MotionEvent.ACTION_DOWN:
  10. name="ACTION_DOWN";
  11. break;
  12. case MotionEvent.ACTION_MOVE:
  13. name="ACTION_MOVE";
  14. break;
  15. case MotionEvent.ACTION_UP:
  16. name="ACTION_UP";
  17. break;
  18. }
  19. return name;
  20. }
  21. }

运行效果如图:

其中蓝色部分是MyLayoutSecond.java ,红色部分是MyLayoutFirst.java
现在我点击一下蓝色部分:运行结果如图:

从图中可以看出,事件最先被Activity捕获,然后分发给 MyLayoutFirst,MyLayoutFirst首先调用自身的onInterceptTouchEvent判断是否将该事件拦截,由于默认返回是false,所以没有拦截,从而事件分发给了MyLayoutSecond,MyLayoutSecond同样通过dispatchTouchEvent分发出去,分发出去之前同样检查是否被拦截,默认都是没有被拦截的,但是由于MyLayoutSecond是没有子视图的,所有最终事件有自己处理,调用自身的onTouchEvent方法,由于该方法默认返回的是false,所以认为此事件是没有被消费掉的,继续传递到了MyLayoutFirst中,同样也没有消费这个事件,最终传递到了Mainactivity,继续往后看发现后面的ACTION_MOVE和ACTION_UP并没有传入MyLayoutFirst和MyLayoutSecond,这是因为一旦某一个事件没有被处理,后面的事件是不会被分发的。所以ACTION_MOVE和ACTION_UP直接被MainActivity处理掉了。

下面再看第二种情况:

 

MainActivity

MyLayoutFirst

MyLayoutSecond

dispatchTouchEvent

super.dispatchTouchEvent

super.dispatchTouchEvent

super.dispatchTouchEvent

onInterceptTouchEvent

--

true

super.onInterceptTouchEvent(ev)

onTouchEvent

super.onTouchEvent

super.onTouchEvent

super.onTouchEvent

运行结果如下:

从图中可以看出,事件传递到了MyLayoutFirst后没有分发到MyLayoutSecond,直接调用自身的onTouchEvent,由于返回的是false,导致事件没有消费,最终传递给了MainActivity,
而且后续事件也没有传递到MyLayoutFirst和MyLayoutSecond,直接被MainActivity处理

第三种情况:

 

MainActivity

MyLayoutFirst

MyLayoutSecond

dispatchTouchEvent

super.dispatchTouchEvent

super.dispatchTouchEvent

super.dispatchTouchEvent

onInterceptTouchEvent

--

true

super.onInterceptTouchEvent(ev)

onTouchEvent

super.onTouchEvent

true

super.onTouchEvent

运行结果:

和情况二不同的是MyLayoutFirst的onTouchEvent返回了true,也就是说MyLayoutFirst消费了此事件,所以ACTION_DOWN也没有再传给MainActivity,并且ACTION_MOVE和ACTION_UP
均传给了MyLayoutFirst

第四中情况:

 

MainActivity

MyLayoutFirst

MyLayoutSecond

dispatchTouchEvent

super.dispatchTouchEvent

super.dispatchTouchEvent

super.dispatchTouchEvent

onInterceptTouchEvent

--

super.onInterceptTouchEvent(ev)

super.onInterceptTouchEvent(ev)

onTouchEvent

super.onTouchEvent

super.onTouchEven

true

运行结果:

发现所有的事件都是传递到了MyLayoutSecond后被消费了

其实还有很多其他组合方式,大家如果又兴趣可以自己尝试改变每个函数的返回值,查看打印结果,这里我就不一一列举了。。。。。

最后我会提供一个小demo演示如何解决滑动冲突,背景如下:
一个ViewPager里面包含两个Framgent,有一个Fragment里面有一个HorizontalListView ,如何滑动冲突?
我就贴出关键代码吧

  1. horizontal=(HorizontalListView)view.findViewById(R.id.hscroll);
  2. horizontal.setOnTouchListener(new OnTouchListener()
  3. {
  4. @Override
  5. public boolean onTouch(View arg0, MotionEvent event)
  6. {
  7. if(event.getAction()==MotionEvent.ACTION_DOWN)
  8. {
  9. parent.requestDisallowInterceptTouchEvent(true);
  10. }else if(event.getAction()==MotionEvent.ACTION_UP)
  11. {
  12. parent.requestDisallowInterceptTouchEvent(false);
  13. }
  14. return false;
  15. }
  16. });

加入这段代码就可以避免滑动冲突了,至于为什么大家可以参考我的前以前文章《Android Touch 事件传递机制详解 上》 这两个demo的例子我均会上传下载的

Android Touch事件传递机制详解 下的更多相关文章

  1. Android Touch事件传递机制详解 上

    最近总是遇到关于Android Touch事件的问题,如:滑动冲突的问题,以前也花时间学习过Android Touch事件的传递机制,可以每次用起来的时候总是忘记了,索性自己总结一下写篇文章避免以后忘 ...

  2. Android Touch事件传递机制详解

    Android开发的朋友经常处理各种触摸事件,然而在触摸事件的传递过程中主要用到三个方法:dispatchTouchEvent().onInterceptTouchEvent()和onTouchEve ...

  3. Android 的事件传递机制,详解

    Android 的事件传递机制,详解 前两天和一个朋友聊天的时候.然后说到事件传递机制.然后让我说的时候,忽然发现说的不是非常清楚,事实上Android 的事件传递机制也是知道一些,可是感觉自己知道的 ...

  4. Android Touch事件传递机制具体解释 下

    尊重原创:http://blog.csdn.net/yuanzeyao/article/details/38025165 资源下载:http://download.csdn.net/detail/yu ...

  5. Android Touch事件传递机制 二:单纯的(伪生命周期)

    转载于:http://blog.csdn.net/yuanzeyao/article/details/38025165 在前一篇文章中,我主要讲解了Android源码中的Touch事件的传递过程,现在 ...

  6. Android Touch事件传递机制 二:单纯的(伪生命周期) 这个清楚一点

    转载于:http://blog.csdn.net/yuanzeyao/article/details/38025165 在前一篇文章中,我主要讲解了Android源码中的Touch事件的传递过程,现在 ...

  7. Android事件传递机制详解及最新源码分析——ViewGroup篇

    版权声明:本文出自汪磊的博客,转载请务必注明出处. 在上一篇<Android事件传递机制详解及最新源码分析--View篇>中,详细讲解了View事件的传递机制,没掌握或者掌握不扎实的小伙伴 ...

  8. Android Touch事件传递机制 一: OnTouch,OnItemClick(监听器),dispatchTouchEvent(伪生命周期)

      ViewGroup View  Activity dispatchTouchEvent 有 有 有 onInterceptTouchEvent 有 无 无 onTouchEvent 有 有 有 例 ...

  9. Android touch 事件传递机制

    前言: (1)在自定义view的时候经常会遇到事件拦截处理,比如在侧滑菜单的时候,我们希望在侧滑菜单里面有listview控件,但是我们希望既能左右滑动又能上下滑动,这个时候就需要对触摸的touch事 ...

随机推荐

  1. 【Triangle 】cpp

    题目: Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjace ...

  2. 【SCOI 2010】传送带

    为了方便,我们不妨设$\rm P \lt Q,R$ 我们发现,有$\rm E$点在$\rm AB$上,$\rm F$点在$\rm CD$上,最优解一定是$\rm AE\rightarrow EF\ri ...

  3. flask url_for()和redirect的区别

    一. 两者用来重定向的时候,被操作的对象不同. redirect直接是url,就是app.route的路径参数. url_for()是对函数进行操作. from flask import Flask, ...

  4. 隐匿攻击-ICMP

    ICMP隐蔽隧道从入门到精通 概述 众所周知传统socket隧道已极少,tcp.upd大量被防御系统拦截,dns.icmp.http/https等难于禁止的协议(当然还有各种xx over dns/i ...

  5. python中subprocess.Popen的args和shell参数的使用

    subprocess模块定义了一个类: Popen class subprocess.Popen( args,        bufsize=0,        executable=None,    ...

  6. 第三篇:python基础_3

    本篇内容 文件处理补充 函数基本语法及特性 参数 返回值 嵌套函数 一.文件处理补充 1.文件操作的内置方法 #!/usr/bin/env pyhon #encoding: utf-8 #auth: ...

  7. [USACO12Jan][luogu3041] Video Game Combos [AC自动机+dp]

    题面 传送门 思路 首先,有一个非常显然的思路就是dp: 设$dp[i][j]$表示前i个字符,最后一个为j 然后发现这个东西有后效性 改!设$dp[i][j]$代表前i个字符,最后15个的状态为j( ...

  8. HDU 3792 素数打表

    Description If we define dn as: dn = pn+1-pn, where pi is the i-th prime. It is easy to see that d1 ...

  9. Render 使用

    Page页面文件,重新Render 方法,目的是把页面的ViewState信息放在最后,利于页面展示速度和SEO优化. Render方法对于重新Html控件还是很好用的. private static ...

  10. hihocoder #1415 : 后缀数组三·重复旋律3

    #1415 : 后缀数组三·重复旋律3 Time Limit:5000ms Case Time Limit:1000ms Memory Limit:256MB 描述 小Hi平时的一大兴趣爱好就是演奏钢 ...