您现在的位置是:首页 > 文章详情

浅谈Android 事件分发机制(一)

日期:2018-04-28点击:320

Android事件分发机制是Android开发者必须了解的知识,这方面的内容很多,自己纯看文章总觉得比较抽象,自己写了个demo,理一下事件分发的流程,加深印象。

view结构

image

PhoneWindow 的指示通过 DecorView 传递给下面的 View,下面 View 的信息也通过 DecorView 回传给 PhoneWindow。这里我们主要聊聊ViewGroup与view的事件分发

类型 相关方法 ViewGroup View
事件分发 dispatchTouchEvent
事件拦截 onInterceptTouchEvent ×
事件消费 onTouchEvent

事件分发dispatchTouchEvent一般改写不多,主要关注另外两个。
事件拦截onInterceptTouchEvent,true,拦截,交给自己的onTouchEvent处理,不传给下级;false,不拦截,传给下级。
事件消费onTouchEvent,true,自己搞定消费,不用上传;false,上传。

事件模拟

image

如图布局,最外层的父布局ViewGroupA,中间层的ViewGroupB,最里层的ViewC

<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto"> <com.qhyccd.event.ViewGroupA app:layout_constraintTop_toTopOf="parent" android:layout_marginTop="100dp" android:layout_width="300dp" android:layout_height="300dp" android:background="@color/colorRed"> <com.qhyccd.event.ViewGroupB android:layout_width="200dp" android:layout_height="200dp" android:background="@color/colorYellow"> <com.qhyccd.event.ViewC android:layout_width="100dp" android:layout_height="100dp" android:background="@color/colorBlue" /> </com.qhyccd.event.ViewGroupB> </com.qhyccd.event.ViewGroupA> </FrameLayout> 

首先模拟下以上场景,A、B、C三个角色,A>B>C

ViewGroupA

public class ViewGroupA extends LinearLayout { public ViewGroupA(Context context) { super(context); } public ViewGroupA(Context context, @Nullable AttributeSet attrs) { super(context, attrs); } public ViewGroupA(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { Log.i("》》》", " ViewGroupA dispatchTouchEvent "); return super.dispatchTouchEvent(ev); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { Log.i("》》》", " ViewGroupA onInterceptTouchEvent "); return super.onInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { Log.i("》》》", " ViewGroupA onTouchEvent "); return super.onTouchEvent(event); } } 

ViewGroupB

public class ViewGroupB extends LinearLayout { public ViewGroupB(Context context) { super(context); } public ViewGroupB(Context context, @Nullable AttributeSet attrs) { super(context, attrs); } public ViewGroupB(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { Log.i("》》》", " ViewGroupB dispatchTouchEvent "); return super.dispatchTouchEvent(ev);; } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { Log.i("》》》", " ViewGroupB onInterceptTouchEvent "); return super.onInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { Log.i("》》》", " ViewGroupB onTouchEvent "); return super.onTouchEvent(event); } } 

ViewC

public class ViewC extends View { public ViewC(Context context) { super(context); } public ViewC(Context context, @Nullable AttributeSet attrs) { super(context, attrs); } public ViewC(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override public boolean dispatchTouchEvent(MotionEvent event) { Log.i("》》》", " ViewC dispatchTouchEvent "); return super.dispatchTouchEvent(event); } @Override public boolean onTouchEvent(MotionEvent event) { Log.i("》》》", " ViewC onTouchEvent "); return super.onTouchEvent(event); } } 

情景一

默认情况下,点击C区域

ViewGroupA dispatchTouchEvent ViewGroupA onInterceptTouchEvent ViewGroupB dispatchTouchEvent ViewGroupB onInterceptTouchEvent ViewC dispatchTouchEvent ViewC onTouchEvent ViewGroupB onTouchEvent ViewGroupA onTouchEvent 

可见,事件是从A->B->C,再从C->B->A回传

情景二

A想自己把事件拦截,不给下级处理,A里面onInterceptTouchEvent返回ture拦截事件

ViewGroupA dispatchTouchEvent ViewGroupA onInterceptTouchEvent ViewGroupA onTouchEvent 

情景三

B想自己把事件拦截,不给下级处理,B里面onInterceptTouchEvent返回ture拦截事件。

ViewGroupA dispatchTouchEvent ViewGroupA onInterceptTouchEvent ViewGroupB dispatchTouchEvent ViewGroupB onInterceptTouchEvent ViewGroupB onTouchEvent ViewGroupA onTouchEvent 

B这里只是对事件拦截不往下传递,还是会往上回传的。
如果想让B自己把事件消费,不往上级传递,B的onTouchEvent返回true

ViewGroupA dispatchTouchEvent ViewGroupA onInterceptTouchEvent ViewGroupB dispatchTouchEvent ViewGroupB onInterceptTouchEvent ViewGroupB onTouchEvent 

情景四

C属于最底层view,对事件没有拦截权限,C自己想把事件消费了,C的onTouchEvent返回true,不再往上级回传

ViewGroupA dispatchTouchEvent ViewGroupA onInterceptTouchEvent ViewGroupB dispatchTouchEvent ViewGroupB onInterceptTouchEvent ViewC dispatchTouchEvent ViewC onTouchEvent 

以上是静态点击事件处理流程,模拟的事件分发机制,通过log打印可以看到事件的传递流程,这篇文章属于基础篇章,后续我们给view添加滑动,通过处理滑动冲突进一步理解事件的分发机制,敬请期待下一篇。

END

祝大家五一劳动节快乐!致敬奋斗在一线的码农!

欢迎关注微信号

image.png

原文链接:https://yq.aliyun.com/articles/610898
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章