Android Touch事件传递机制具体解释 下
尊重原创: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
public class MyLayoutFirst extends LinearLayout
{
private static final String TAG = "MyLayoutFirst";
public MyLayoutFirst(Context context, AttributeSet attrs)
{
super(context, attrs);
} @Override
public boolean onInterceptTouchEvent(MotionEvent ev)
{
Log.w("yzy", "MyLayoutFirst->onInterceptTouchEvent->"+MyUtils.getActionName(ev));
return super.onInterceptTouchEvent(ev);
} @Override
public boolean onTouchEvent(MotionEvent event)
{
Log.e("yzy", "MyLayoutFirst->onTouchEvent->"+MyUtils.getActionName(event));
return super.onTouchEvent(event);
} @Override
public boolean dispatchTouchEvent(MotionEvent ev)
{
Log.i("yzy", "MyLayoutFirst->dispatchTouchEvent->"+MyUtils.getActionName(ev));
return super.dispatchTouchEvent(ev);
} }
自己定义一个类;MyLayoutSecond.java
public class MyLayoutSecond extends LinearLayout
{
private static final String TAG = "MyLayoutSecond";
public MyLayoutSecond(Context context, AttributeSet attrs)
{
super(context, attrs);
} @Override
public boolean onTouchEvent(MotionEvent event)
{
Log.e("yzy", "MyLayoutSecond->MyLayoutSecond->"+MyUtils.getActionName(event));
return super.onTouchEvent(event);
} @Override
public boolean onInterceptTouchEvent(MotionEvent ev)
{
Log.w("yzy", "MyLayoutSecond->onInterceptTouchEvent->"+MyUtils.getActionName(ev));
return super.onInterceptTouchEvent(ev);
} @Override
public boolean dispatchTouchEvent(MotionEvent ev)
{
Log.i("yzy", "MyLayoutSecond->dispatchTouchEvent->"+MyUtils.getActionName(ev));
return super.dispatchTouchEvent(ev);
} }
增加到main_layout.xml中
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
> <com.event.demo.MyLayoutFirst
android:id="@+id/layout_first"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FF0000"
>
<com.event.demo.MyLayoutSecond
android:id="@+id/layout_second"
android:layout_width="320dip"
android:layout_height="120dip"
android:layout_gravity="center"
android:background="#0000FF"
> </com.event.demo.MyLayoutSecond>
</com.event.demo.MyLayoutFirst> </RelativeLayout>
MainActivity中增加onTouchEvent方法
public class MainActivity extends Activity
{ @Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
} @Override
public boolean onCreateOptionsMenu(Menu menu)
{
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
} @Override
public boolean dispatchTouchEvent(MotionEvent ev)
{
Log.i("yzy", "MainActivity->dispatchTouchEvent->"+MyUtils.getActionName(ev));
return super.dispatchTouchEvent(ev);
} @Override
public boolean onTouchEvent(MotionEvent event)
{
Log.e("yzy", "MainActivity->onTouchEvent->"+MyUtils.getActionName(event));
return super.onTouchEvent(event);
}
}
最后就一个工具类,用来将事件id转换为字符串。
public class MyUtils
{
private static final String TAG = "MyUtils";
public static String getActionName(MotionEvent event)
{
String name="";
switch(event.getAction())
{
case MotionEvent.ACTION_DOWN:
name="ACTION_DOWN";
break;
case MotionEvent.ACTION_MOVE:
name="ACTION_MOVE";
break;
case MotionEvent.ACTION_UP:
name="ACTION_UP";
break;
}
return name;
}
}
执行效果如图:
当中蓝色部分是MyLayoutSecond.java ,红色部分是MyLayoutFirst.java
如今我点击一下蓝色部分:执行结果如图:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveXVhbnpleWFv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">
从图中能够看出,事件最先被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 |
执行结果例如以下:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveXVhbnpleWFv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">
从图中能够看出,事件传递到了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 ,怎样滑动冲突?
我就贴出关键代码吧
horizontal=(HorizontalListView)view.findViewById(R.id.hscroll);
horizontal.setOnTouchListener(new OnTouchListener()
{ @Override
public boolean onTouch(View arg0, MotionEvent event)
{
if(event.getAction()==MotionEvent.ACTION_DOWN)
{
parent.requestDisallowInterceptTouchEvent(true);
}else if(event.getAction()==MotionEvent.ACTION_UP)
{
parent.requestDisallowInterceptTouchEvent(false);
}
return false;
}
});
增加这段代码就能够避免滑动冲突了,至于为什么大家能够參考我的前曾经文章《Android Touch 事件传递机制具体解释 上》 这两个demo的样例我均会上传下载的
Android Touch事件传递机制具体解释 下的更多相关文章
- Android Touch事件传递机制详解 下
尊重原创:http://blog.csdn.net/yuanzeyao/article/details/38025165 资源下载:http://download.csdn.net/detail/yu ...
- Android Touch事件传递机制具体解释 上
尊重原创:http://blog.csdn.net/yuanzeyao/article/details/37961997 近期总是遇到关于Android Touch事件的问题,如:滑动冲突的问题,曾经 ...
- Android touch 事件传递机制
前言: (1)在自定义view的时候经常会遇到事件拦截处理,比如在侧滑菜单的时候,我们希望在侧滑菜单里面有listview控件,但是我们希望既能左右滑动又能上下滑动,这个时候就需要对触摸的touch事 ...
- Android Touch事件传递机制 一: OnTouch,OnItemClick(监听器),dispatchTouchEvent(伪生命周期)
ViewGroup View Activity dispatchTouchEvent 有 有 有 onInterceptTouchEvent 有 无 无 onTouchEvent 有 有 有 例 ...
- Android Touch事件传递机制通俗讲解
在讲正题之前我们讲一段有关任务传递的小故事,抛砖迎玉下: 话说一家软件公司,来一个任务,分派给了开发经理去完成: 开发经理拿到,看了一下,感觉好简单,于是 开发经理:分派给了开发组长 开发组长:分派给 ...
- Android Touch事件传递机制引发的血案
尊重原创:http://blog.csdn.net/yuanzeyao/article/details/38942135 关于Android Touch事件传递机制我之前也写过两篇文章,自觉得对Tou ...
- Android Touch事件传递机制 二:单纯的(伪生命周期)
转载于:http://blog.csdn.net/yuanzeyao/article/details/38025165 在前一篇文章中,我主要讲解了Android源码中的Touch事件的传递过程,现在 ...
- Android Touch事件传递机制 二:单纯的(伪生命周期) 这个清楚一点
转载于:http://blog.csdn.net/yuanzeyao/article/details/38025165 在前一篇文章中,我主要讲解了Android源码中的Touch事件的传递过程,现在 ...
- (转)Android Touch事件传递机制
-----来源:http://www.trinea.cn/android/touch-event-delivery-mechanism/ 介绍Android Touch事件的传递机制. 不少朋友私信问 ...
随机推荐
- loadrunner rtsp协议模拟
在核心网做过3年的sip消息模拟,所以rtsp消息模拟只要知道信令消息交互就非常顺利了 RTSP 实时流传输协议, 是TCP/IP协议体系中的一个应用层协议, 该协议定义了一对多应用程序如何有效地通过 ...
- Win右键管理员权限的获取
Windows Registry Editor Version 5.00 ;取得文件修改权限 [HKEY_CLASSES_ROOT\*\shell\runas] @="管理员权限" ...
- 【bzoj3916】[Baltic2014]friends 字符串hash
题目描述 有三个好朋友喜欢在一起玩游戏,A君写下一个字符串S,B君将其复制一遍得到T,C君在T的任意位置(包括首尾)插入一个字符得到U.现在你得到了U,请你找出S. 输入 第一行一个数N,表示U的长度 ...
- BZOJ2121 字符串游戏 【dp】
题目链接 BZOJ2121 题解 dp怎么那么神呐QAQ 我们要求出最小字符串长度 我们设一个\(dp[i]\)表示前\(i\)个字符最后所形成的最短字符串长度 对于第\(i\)个字符,要么保留,就是 ...
- bzoj2338数矩形(rectangle)
数矩形(rectangle) 计算几何 把所有点两两连线,把这些线按长度排序,再按中点排序 能组成矩形的线一定是连续的 最坏就是所有点围成一个圆,交于圆心 复杂度O(可以过) 要用叉积,不然会被卡精 ...
- exit() 与 return() 的区别
exit()与 return() 的区别为: 1. return返回函数值,是关键字: exit 是一个函数. 2. return是语言级别的,它表示了调用堆栈的返回:而exit是系统调用级别的,它 ...
- [暑假集训--数论]poj1595 Prime Cuts
A prime number is a counting number (1, 2, 3, ...) that is evenly divisible only by 1 and itself. In ...
- HTML+CSS之iframe
碎碎:这两天在实践中,用到了 iframe,之前对其不甚了解,了解之中遇到好多奇葩问题,今天记录下这两天遇到的相关的内容. 嵌入的 iframe 页面的边框 嵌入的 iframe 页面的背景 嵌入的 ...
- 【BZOJ4300】绝世好题(二进制,DP)
题意: n<=100000,ai<=2*10^9 思路:按二进制逐位考虑,只要有至少1位取and后为1就可以接下去 设dp[i]为第i位取and之后为1的最长的序列长度,意会一下 #inc ...
- linux下的用户组管理
用户组管理分两类 如果赋给组什么权限,那么组员就会有什么权限 1.私有组 在创建新用户的时候,就要为用户指定组.如果没有指定,就会默认创建一个与用户名相同的用户组,这个用户组只有该用户一个用户,就被称 ...