浅谈android中View的事件分发机制

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

猜你喜欢

转载自blog.csdn.net/baidu_32015283/article/details/87972383
今日推荐