重写Android事件分发机制

实践是检验真理的唯一标准!

重写事件分发机制,布局如下:

布局代码如下:
<com.example.mayn.mytesteventdispatchpro.MyOuterViewGroup
    android:id="@+id/outer"
    android:background="#ff0000"
    android:layout_width="350dp"
    android:layout_height="250dp">
    <com.example.mayn.mytesteventdispatchpro.MyInnerViewGroup
        android:id="@+id/inner"
        android:background="#ffff00"
        android:layout_width="250dp"
        android:layout_gravity="center|center_horizontal"
        android:layout_height="150dp">
        <com.example.mayn.mytesteventdispatchpro.MyView
            android:layout_width="150dp"
            android:layout_height="75dp"
            android:background="#0000ff"
            android:layout_gravity="center"
            android:id="@+id/view"
            />
    </com.example.mayn.mytesteventdispatchpro.MyInnerViewGroup>
</com.example.mayn.mytesteventdispatchpro.MyOuterViewGroup>

每一个自定义view都重写了dispatchTouchEvent和onTouchEvent方法,viewGroup还重写了onInterceptTouchEvent方法。具体如下: 

@Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        Log.e("TEST","MyOuterViewGroup dispatchTouchEvent");
        switch (ev.getAction()){
            case MotionEvent.ACTION_DOWN:
                Log.e("TEST","MyOuterViewGroup dispatchTouchEvent ACTION_DOWN");
                break;
            case MotionEvent.ACTION_MOVE:
                Log.e("TEST","MyOuterViewGroup dispatchTouchEvent ACTION_MOVE");
                break;
            case MotionEvent.ACTION_UP:
                Log.e("TEST","MyOuterViewGroup dispatchTouchEvent ACTION_UP");
                break;
        }
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        Log.e("TEST","MyOuterViewGroup onInterceptTouchEvent");
        switch (ev.getAction()){
            case MotionEvent.ACTION_DOWN:
                Log.e("TEST","MyOuterViewGroup onInterceptTouchEvent ACTION_DOWN");
                break;
            case MotionEvent.ACTION_MOVE:
                Log.e("TEST","MyOuterViewGroup onInterceptTouchEvent ACTION_MOVE");
                break;
            case MotionEvent.ACTION_UP:
                Log.e("TEST","MyOuterViewGroup onInterceptTouchEvent ACTION_UP");
                break;
        }
        return super.onInterceptTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        Log.e("TEST","MyOuterViewGroup onTouchEvent");
        switch (ev.getAction()){
            case MotionEvent.ACTION_DOWN:
                Log.e("TEST","MyOuterViewGroup onTouchEvent ACTION_DOWN");
                break;
            case MotionEvent.ACTION_MOVE:
                Log.e("TEST","MyOuterViewGroup onTouchEvent ACTION_MOVE");
                break;
            case MotionEvent.ACTION_UP:
                Log.e("TEST","MyOuterViewGroup onTouchEvent ACTION_UP");
                break;
        }
        return super.onTouchEvent(ev);
    }

 以下是举例各种点击情况下的事件分发:

一、点击外部viewgroup:

E/TEST: MyOuterViewGroup dispatchTouchEvent
E/TEST: MyOuterViewGroup dispatchTouchEvent ACTION_DOWN
E/TEST: MyOuterViewGroup onInterceptTouchEvent
E/TEST: MyOuterViewGroup onInterceptTouchEvent ACTION_DOWN
E/TEST: MyOuterViewGroup onTouchEvent
E/TEST: MyOuterViewGroup onTouchEvent ACTION_DOWN
E/TEST: MyOuterViewGroup dispatchTouchEvent
E/TEST: MyOuterViewGroup dispatchTouchEvent ACTION_MOVE
E/TEST: MyOuterViewGroup onTouchEvent
E/TEST: MyOuterViewGroup onTouchEvent ACTION_MOVE

E/TEST: MyOuterViewGroup dispatchTouchEvent
E/TEST: MyOuterViewGroup dispatchTouchEvent ACTION_UP
E/TEST: MyOuterViewGroup onTouchEvent
E/TEST: MyOuterViewGroup onTouchEvent ACTION_UP
E/TEST: Outer ViewGroup onClick

1)从上面可以看出,当点击外部viewGroup的时候,只有MyOuterViewGroup的事件分发方法有响应,分别调用dispatchTouchEvent和onTouchEvent方法,不论onInterceptTouchEvent方法返回默认还是true/false,在ACTION_MOVE和ACTION_UP时都不会去调用该方法了

2)当dispatchTouchEvent返回false的时候,只会调用该方法的ACTION_DOWN,其余方法全部无响应,拦截。

3)当dispatchTouchEvent返回true的时候,

E/TEST: MyOuterViewGroup dispatchTouchEvent
E/TEST: MyOuterViewGroup dispatchTouchEvent ACTION_DOWN
E/TEST: MyOuterViewGroup dispatchTouchEvent
E/TEST: MyOuterViewGroup dispatchTouchEvent ACTION_MOVE
E/TEST: MyOuterViewGroup dispatchTouchEvent
E/TEST: MyOuterViewGroup dispatchTouchEvent ACTION_UP

该方法的所有ACTION都有响应。但是onTouchEvent方法无响应,拦截

4)当dispatchTouchEvent返回为默认,不论onInterceptTouchEvent方法返回默认还是true/false,都会分发到onTouchEvent方法去。不拦截

5)当onTouchEvent返回为true时,

MyOuterViewGroup dispatchTouchEvent ACTION_DOWN
MyOuterViewGroup onInterceptTouchEvent ACTION_DOWN
MyView dispatchTouchEvent ACTION_DOWN
MyOuterViewGroup dispatchTouchEvent ACTION_MOVE
MyOuterViewGroup onInterceptTouchEvent ACTION_MOVE
MyOuterViewGroup dispatchTouchEvent ACTION_UP
MyOuterViewGroup onInterceptTouchEvent ACTION_UP
Inner ViewGroup onClick

所有ACTION都有响应,但是onClick事件无响应,拦截。但是内部的ViewGroup有onClick响应

6)当onTouchEvent返回为false时,

E/TEST: MyOuterViewGroup dispatchTouchEvent
E/TEST: MyOuterViewGroup dispatchTouchEvent ACTION_DOWN
E/TEST: MyOuterViewGroup onInterceptTouchEvent
E/TEST: MyOuterViewGroup onInterceptTouchEvent ACTION_DOWN
E/TEST: MyOuterViewGroup onTouchEvent
E/TEST: MyOuterViewGroup onTouchEvent ACTION_DOWN

同上面第2)条,只会调用ACTION_DOWN方法,其余全无响应。拦截

二、点击内部View

1)全部返回为默认情况下:
MyOuterViewGroup dispatchTouchEvent ACTION_DOWN
MyOuterViewGroup onInterceptTouchEvent ACTION_DOWN
MyView dispatchTouchEvent ACTION_DOWN
MyView onTouchEvent ACTION_DOWN
MyOuterViewGroup dispatchTouchEvent ACTION_MOVE
MyOuterViewGroup onInterceptTouchEvent ACTION_MOVE
MyView dispatchTouchEvent ACTION_MOVE
MyView onTouchEvent ACTION_MOVE
MyOuterViewGroup dispatchTouchEvent ACTION_UP
MyOuterViewGroup onInterceptTouchEvent ACTION_UP
MyView dispatchTouchEvent ACTION_UP
MyView onTouchEvent ACTION_UP
View onClick

从上面可以看出,全部返回默认的时候,先调用外部的viewgroup,然后调用内部的view。1.1)当外部viewgroup的dispatchTouchEvent返回false/true的时候,直接拦截;1.2)当外部viewgroup的onInterceptTouchEvent 返回false和true的时候,拦截,只有外部viewgroup有响应,外部viewgroup可以响应点击事件。

2)内部view的dispatchTouchEvent返回true时,该方法的所有ACTION都有响应。但是onTouchEvent方法无响应,拦截

3)内部view的dispatchTouchEvent返回false时,只会调用该方法的ACTION_DOWN,外部InnerViewGroup的onClick响应。

三、结论如下:

1、对于dispatchTouchEvent方法,

1.1如果是viewgroup,1)返回为true则拦截,2)如果返回为false,则a)当前VG是最外层,则拦截,b)当前VG不是最外层,不论点击当前VG还是内部view,都是外层VG的onClick响应

1.2如果是view,1)返回true则拦截,2)返回false,上一层的VG的onClick响应

2、对于onInterceptTouchEvent方法,只有ViewGroup有,1)返回为true,则拦截,自己的onClick响应,2)返回为false,不拦截,点自己,自己的onClick响应,点内V,内V的onClick响应

3、对于onTouchEvent方法,

1.1如果是viewgroup,1)返回为true,则a)点自己,拦截,b)点内部view,不拦截,内部view的onClick响应。2)返回为false,则a)点自己,拦截,外部的VG的onClick响应,b)点内view,不拦截,内view的onClick响应

1.2如果是view,1)返回true则拦截,2)返回false,则上一层的onClick响应

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值