浅谈Android自定义View事件传递机制
来源:互联网 发布:淘宝基础店铺全屏代码 编辑:程序博客网 时间:2024/06/05 07:32
本人作为一个技术小菜鸟,第一次写博客,有写的不好的地方希望大家多多指教,本文章一来给大家做个参考,二来说不定哪天忘记了回来看看也是好的。哈哈,废话不多说,直接进入主题!
事件传递所涉及到的方法
- dispatchTouchEvent() 分发方法
- onInterceptTouchEvent() 拦截方法
- onTouchEvent() 消费方法
首先简单介绍下这三个方法 :
dispatchTouchEvent() 这个方法代表事件分发,作用是改变事件传递的方向。
onInterceptTouchEvent()对事件进行拦截,作用拦截事件交给当前处理或传递到下一级。
onTouchEvent()主要的作用是消费MotionEvent事件。
Activity和View中是没有事件拦截方法,只有分发和消费方法,具体Why这个要问谷歌了! 哈哈 这个不做解释 ..
首先我们看一下三个方法 返回的是super.XX() 还有两种返回值true/false .
- 分发
返回true时代表事件不分发,事件到此结束。
返回false时,会把事件传递给上一级的onTouchEvent()处理。
返回super.dispatchTouchEvent(ev)时分两种情况,一种是ViewGroup 会把事件传递给当前的onInterceptTouchEvent()方法处理,另一种是View 直接交给当前的onTouchEvent()事件处理。 - 拦截
返回true时,会把事件传递给当前的onTouchEvent()处理。
返回false/super.onInterceptTouchEvent(ev) 这个时候代表事件不拦截,事件会传向下一级的dispatchTouchEvent()。 - 消费
返回true时代表此次是事件已消费,并且以后的事件如果中途没被拦截的话会一直走到当前方向
返回false/super.onTouchEvent(ev) 这个时候代表事件不拦截,事件会传向上一级的onTouchEvent()。
@Override public boolean dispatchTouchEvent(MotionEvent ev) { return super.dispatchTouchEvent(ev);//true/false } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { return super.onInterceptTouchEvent(ev);//true/false } @Override public boolean onTouchEvent(MotionEvent event) { return super.onTouchEvent(event);//true/false }
动手做个demo
首先准备一个Activity
创建三个自定义View(其实两个就可以) FatherA,FatherB,ChildC
CustomViewActivity
public class CustomViewActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState, PersistableBundle persistentState) { super.onCreate(savedInstanceState, persistentState); setContentView(R.layout.activity_custom); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { return super.dispatchTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { return super.onTouchEvent(event); }}
FatherA
public class FatherA extends LinearLayout { public FatherA(Context context) { super(context); } public FatherA(Context context, AttributeSet attrs) { super(context, attrs); } public FatherA(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { return super.dispatchTouchEvent(ev);//true } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { return super.onInterceptTouchEvent(ev);//true } @Override public boolean onTouchEvent(MotionEvent event) { return super.onTouchEvent(event); }}
FatherB和FatherA一样 此处省略
ChildC
public class ChildC extends View { public ChildC(Context context) { super(context); } public ChildC(Context context, AttributeSet attrs) { super(context, attrs); } public ChildC(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override public boolean dispatchTouchEvent(MotionEvent event) { return super.dispatchTouchEvent(event); } @Override public boolean onTouchEvent(MotionEvent event) { return super.onTouchEvent(event); }}
最后贴一个主布局的xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical"> <com.sincerly.android.activity.customView.view.FatherA android:layout_width="300dp" android:layout_height="300dp" android:gravity="center" android:background="@color/blue"> <com.sincerly.android.activity.customView.view.FatherB android:layout_width="200dp" android:background="@color/green" android:gravity="center" android:layout_height="200dp"> <com.sincerly.android.activity.customView.view.ChildC android:layout_width="100dp" android:layout_height="100dp" android:background="@color/white"/> </com.sincerly.android.activity.customView.view.FatherB> </com.sincerly.android.activity.customView.view.FatherA></LinearLayout>
测试一,点击FatherB(绿色区域),FatherA的分发方法返回true,其他都为默认
E/tag: CustomViewActivity DispatchTouchEvent()E/tag: FatherA DispatchTouchEvent()E/tag: CustomViewActivity DispatchTouchEvent()E/tag: FatherA DispatchTouchEvent()
可以根据Log看出FatherB这个View根本没获取到事件 因为FatherA的分发方法返回了true,就好像给事件加了个标示 如果到FatherA的分发方法事件就无效了。
下面我们把FatherA分发事件改为false
E/tag: CustomViewActivity DispatchTouchEvent()E/tag: FatherA DispatchTouchEvent()E/tag: CustomViewActivity onTouchEvent()E/tag: CustomViewActivity DispatchTouchEvent()E/tag: CustomViewActivity onTouchEvent()
分发方法返回false把事件进行向上传递,给上级的onTouchEvent()处理。
下面我们把FatherA分发事件改为super.dispatchTouchEvent(ev)
E/tag: CustomViewActivity DispatchTouchEvent()E/tag: FatherA DispatchTouchEvent()E/tag: FatherA onInterceptTouchEvent()E/tag: FatherB DispatchTouchEvent()E/tag: FatherB onInterceptTouchEvent()E/tag: FatherB onTouchEvent()E/tag: FatherA onTouchEvent()E/tag: CustomViewActivity onTouchEvent()E/tag: CustomViewActivity DispatchTouchEvent()E/tag: CustomViewActivity onTouchEvent()
可见分发事件只有返回super.dispatchTouchEvent(ev)才会进行分发。
这里解释一下,点击的是绿色 也就是FatherB,处理流程,FatherA分发返回super.d() 进行传递至FatherA的拦截方法 拦截方法返回的super.onInterceptTouchEvent() 不进行拦截 并将事件传递给FatherB的分发事件 然后同理 FatherB 进行分发 ,不拦截(因为我们点击的是绿色区域 并没有点击到ChildC(内层白色区域) ) 所以不拦截之后, 交给当前(FatherB)的onTouchEvent()处理 因为返回的false,所以事件向上传递给FatherA的onTouchEvent() 因为返回的false 所以向上传递给Activity的onTouchEvent()处理.
拦截方法和消费方法 返回super和false的区别 有兴趣可以自行测试,因为效果一样,我这里不做过多解释了。
下面我们测试一下FatherA的拦截方法,返回true
E/tag: CustomViewActivity DispatchTouchEvent()E/tag: FatherA DispatchTouchEvent()E/tag: FatherA onInterceptTouchEvent()E/tag: FatherA onTouchEvent()E/tag: CustomViewActivity onTouchEvent()E/tag: CustomViewActivity DispatchTouchEvent()E/tag: CustomViewActivity onTouchEvent()
可见虽然点击了FatherB ,但是在A处 事件已经拦截。
下图为当前事件的返回值,A拦截返回true,然后走A的onTouchEvent() 返回false,事件并没有被消费, 所以返回Activity的onTouchEvent() 然后整个事件处理完毕。
记得之前有一个例子不错 我引用一下。
校长 教师 班长 小明
校长有一张表不想写,就把这张表下发给教师 说:”你帮我填一下”,然后这个老师也比较懒,然后给班长, 班长有急事然后交给小明说 “帮忙填一下”,小明不会写 ,然后给班长说:”我不会写”, 班长给老师说“我有事 写不了”,然后老师给校长说我不想填(哈哈,找抽),最终表还是到了校长的手中。
如果教师一开始就说“没问题”, 这就是拦截方法 为true 并且如果表填完了,onTouchEvent()方法就为true 也就是说这个表已经填好了, 而且下次再来一张表的时候 还是到这个地方结束。
再做最后一个测试 就是FatherB的拦截返回true,消费返回true
其他全为super.();
E/tag: CustomViewActivity DispatchTouchEvent()E/tag: FatherA DispatchTouchEvent()E/tag: FatherA onInterceptTouchEvent()E/tag: FatherB DispatchTouchEvent()E/tag: FatherB onInterceptTouchEvent()E/tag: FatherB onTouchEvent()E/tag: CustomViewActivity DispatchTouchEvent()E/tag: FatherA DispatchTouchEvent()E/tag: FatherA onInterceptTouchEvent()E/tag: FatherB DispatchTouchEvent()E/tag: FatherB onTouchEvent()
可以看出流程,DOWN事件 进入Activity分发,A分发,A不拦截,到B的 分发,拦截,消费。
由于第一次写博文,经验非常不足,有的解释的没到点上 请谅解,希望对大家有点帮助,缺个流程图,会直观点 ,正在积极制作中。 有没有会做动态图的 那个是什么软件做的? 就是效果演示的那个
- 浅谈Android自定义View事件传递机制
- Android自定义view之事件传递机制
- 浅谈View事件传递机制
- Android事件传递机制详解(嵌套自定义View示例)
- Android View 事件传递机制
- Android View事件传递机制
- Android-view事件传递机制
- 【Android View】 事件传递机制
- android事件传递机制的浅谈
- 浅谈android view事件分发机制
- View事件传递与绘制机制,自定义View实现理解
- Android事件传递机制-View篇
- Android中的View事件传递机制
- Android事件传递机制-View篇
- Android事件传递机制-View篇
- Android View 触摸事件传递机制
- Android View触摸事件传递机制
- Android事件传递机制-View篇
- 获得当前终端名称
- python-002 数组列表问题
- 密码安全的重要性
- Leetcode2 Add Two Numbers
- Android网络开源库-Retrofit(六)源码浅析-上
- 浅谈Android自定义View事件传递机制
- 详解javaScript闭包
- Spring的注入类型(Injection type of Spring)
- 页面压缩图片传到java后台
- FastDFS单台服务器一个tracker多个storage
- register code
- 某通信公司的Android面试题目
- csapp第三章读书笔记
- 10-10———今日学习总结