您的位置:首页 > 移动开发 > Android开发

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

2019-01-13 22:50 726 查看

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

view结构

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

事件分发

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

事件模拟

如图布局,最外层的父布局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添加滑动,通过处理滑动冲突进一步理解事件的分发机制,敬请期待下一篇。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Android