android的事件处理和传递机制实例

android的事件处理机制,相信很多人一开始都比较难懂,如果单单在官网上看流程图,你肯定会很快忘记。那么,遇到比较难懂的知识点,你会怎么做呢?

一是看源码,然后就是写实例加深理解。我选择后者,哈哈,我这里只是想说,如何快速的带大家了解事件处理和传递机制。

那么废话不多说,先把代码贴出来,不懂的地方,大家不妨手把手写代码,多试试。

1.新建一个activity,调出dispatchTouchEvent和onTouchEvent方法。

public class EventTestAct extends Activity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.event_test);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            Log.e("xx", "act dispatchTouchEvent");
        }
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            Log.e("xx", "act onTouchEvent");
        }
        return super.onTouchEvent(event);
    }
}

2.新增两个自定义ViewGroup。调用dispatchTouchEvent,onInterceptTouchEvent,onTouchEvent方法。

public class MyViewGroup1 extends LinearLayout {


    public MyViewGroup1(Context context) {
        super(context);
    }

    public MyViewGroup1(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public MyViewGroup1(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            Log.e("xx", "vp1 dispatchTouchEvent");
        }
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            Log.e("xx", "vp1 onInterceptTouchEvent");
        }
        return super.onInterceptTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.e("xx", "vp1 onTouchEvent");
        return super.onTouchEvent(event);
    }
}

public class MyViewGroup2 extends LinearLayout {


    public MyViewGroup2(Context context) {
        super(context);
    }

    public MyViewGroup2(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public MyViewGroup2(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            Log.e("xx", "vp2 dispatchTouchEvent");
        }
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            Log.e("xx", "vp2 onInterceptTouchEvent");
        }
        return super.onInterceptTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            Log.e("xx", "vp2 onTouchEvent");
        }
        return super.onTouchEvent(event);
    }
}

3.新建一个自定义view,调用dispatchTouchEvent和onTouchEvent方法。

public class MyView extends View {
    public MyView(Context context) {
        super(context);
    }

    public MyView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            Log.e("xx", "mv dispatchTouchEvent");
        }
        return super.dispatchTouchEvent(event);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            Log.e("xx", "mv onTouchEvent");
        }
        return super.onTouchEvent(event);
    }
}
4.创建布局xml。
<?xml version="1.0" encoding="utf-8"?>
<com.kv.mymeet.event.MyViewGroup1 xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/vp1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <com.kv.mymeet.event.MyViewGroup2
        android:id="@+id/vp2"
        android:background="#ffffff"
        android:layout_width="match_parent"
        android:layout_height="300dp">

        <com.kv.mymeet.event.MyView
            android:id="@+id/mv"
            android:background="#ab4a4a"
            android:layout_width="match_parent"
            android:layout_height="50dp" />
    </com.kv.mymeet.event.MyViewGroup2>
</com.kv.mymeet.event.MyViewGroup1>

我们试着写这样一个demo,然后监听action down这个事件,再在上面写上日志。通过修改回调,我们可以观察出事件的传递顺序。

1.什么都没改的情况下做点击,出来的顺序是

12-29 14:55:55.609 4698-4698/com.kv.mymeet E/xx: act dispatchTouchEvent
12-29 14:55:55.619 4698-4698/com.kv.mymeet E/xx: vp1 dispatchTouchEvent
12-29 14:55:55.619 4698-4698/com.kv.mymeet E/xx: vp1 onInterceptTouchEvent
12-29 14:55:55.619 4698-4698/com.kv.mymeet E/xx: vp2 dispatchTouchEvent
12-29 14:55:55.619 4698-4698/com.kv.mymeet E/xx: vp2 onInterceptTouchEvent
12-29 14:55:55.619 4698-4698/com.kv.mymeet E/xx: mv dispatchTouchEvent
12-29 14:55:55.619 4698-4698/com.kv.mymeet E/xx: mv onTouchEvent
12-29 14:55:55.619 4698-4698/com.kv.mymeet E/xx: vp2 onTouchEvent
12-29 14:55:55.619 4698-4698/com.kv.mymeet E/xx: vp1 onTouchEvent
12-29 14:55:55.619 4698-4698/com.kv.mymeet E/xx: act onTouchEvent
可以看得出,事件做从父类做分发,dispatchTouchEvent方法。然后再执行onTouchEvent方法,而onTouchEvent是从子类向父类传。


2.下面我们来操作dispatchTouchEvent方法。

情况1,activity,无论修改dispatchTouchEvent返回值是true或者false,事件都不会再往下面做传递,onTouchEvent的方法均不会触发。(activity层的dispatchTouchEvent方法一般都不会去改)

12-29 15:16:22.719 12659-12659/com.kv.mymeet E/xx: act dispatchTouchEvent

情况2,ViewGroup1层,dispatchTouchEvent返回值为true,事件都不会再往下面做传递,onTouchEvent的方法均不会触发。

12-29 17:11:24.381 8772-8772/com.kv.mymeet E/xx: act dispatchTouchEvent
12-29 17:11:24.391 8772-8772/com.kv.mymeet E/xx: vp1 dispatchTouchEvent

情况3,ViewGroup1层,dispatchTouchEvent返回值为false,事件都不会再往下面做传递,activity层的onTouchEvent方法会触发。

12-30 00:58:05.396 5402-5402/com.kv.mymeet E/xx: act dispatchTouchEvent
12-30 00:58:05.397 5402-5402/com.kv.mymeet E/xx: vp1 dispatchTouchEvent
12-30 00:58:05.398 5402-5402/com.kv.mymeet E/xx: act onTouchEvent

情况4,ViewGroup2层,dispatchTouchEvent返回值为true,事件都不会再往下面做传递,onTouchEvent的方法均不会触发。

12-30 01:05:01.820 6759-6759/com.kv.mymeet E/xx: act dispatchTouchEvent
12-30 01:05:01.821 6759-6759/com.kv.mymeet E/xx: vp1 dispatchTouchEvent
12-30 01:05:01.821 6759-6759/com.kv.mymeet E/xx: vp1 onInterceptTouchEvent
12-30 01:05:01.821 6759-6759/com.kv.mymeet E/xx: vp2 dispatchTouchEvent

情况5,ViewGroup2层,dispatchTouchEvent返回值为false,事件都不会再往下面做传递,activity层和viewgoup1层的onTouchEvent方法会触发。

12-30 01:07:47.201 6759-6759/com.kv.mymeet E/xx: act dispatchTouchEvent
12-30 01:07:47.201 6759-6759/com.kv.mymeet E/xx: vp1 dispatchTouchEvent
12-30 01:07:47.201 6759-6759/com.kv.mymeet E/xx: vp1 onInterceptTouchEvent
12-30 01:07:47.202 6759-6759/com.kv.mymeet E/xx: vp2 dispatchTouchEvent
12-30 01:07:47.203 6759-6759/com.kv.mymeet E/xx: vp1 onTouchEvent
12-30 01:07:47.203 6759-6759/com.kv.mymeet E/xx: act onTouchEvent

情况6,view层,dispatchTouchEvent返回值为true,事件都不会再往下面做传递,onTouchEvent的方法均不会触发。如果想触发ontouchEvent方法,一般子view和父容器的dispatchTouchEvent均不为true

12-30 01:19:12.317 7991-7991/com.kv.mymeet E/xx: act dispatchTouchEvent
12-30 01:19:12.318 7991-7991/com.kv.mymeet E/xx: vp1 dispatchTouchEvent
12-30 01:19:12.318 7991-7991/com.kv.mymeet E/xx: vp1 onInterceptTouchEvent
12-30 01:19:12.318 7991-7991/com.kv.mymeet E/xx: vp2 dispatchTouchEvent
12-30 01:19:12.319 7991-7991/com.kv.mymeet E/xx: vp2 onInterceptTouchEvent
12-30 01:19:12.319 7991-7991/com.kv.mymeet E/xx: mv dispatchTouchEvent


情况7,view层,dispatchTouchEvent返回值为false,activity层,viewgoup1层和viewgroup2层的onTouchEvent方法会触发,view层的ontouchEvent不会触发。(当该层的dispatchTouchEvent设为false值,即不触发当前层及子view的onTouchEvent方法)
12-30 01:10:05.237 7426-7426/com.kv.mymeet E/xx: act dispatchTouchEvent
12-30 01:10:05.238 7426-7426/com.kv.mymeet E/xx: vp1 dispatchTouchEvent
12-30 01:10:05.238 7426-7426/com.kv.mymeet E/xx: vp1 onInterceptTouchEvent
12-30 01:10:05.238 7426-7426/com.kv.mymeet E/xx: vp2 dispatchTouchEvent
12-30 01:10:05.238 7426-7426/com.kv.mymeet E/xx: vp2 onInterceptTouchEvent
12-30 01:10:05.238 7426-7426/com.kv.mymeet E/xx: mv dispatchTouchEvent
12-30 01:10:05.239 7426-7426/com.kv.mymeet E/xx: vp2 onTouchEvent
12-30 01:10:05.239 7426-7426/com.kv.mymeet E/xx: vp1 onTouchEvent
12-30 01:10:05.240 7426-7426/com.kv.mymeet E/xx: act onTouchEvent

3.下面我们来操作viewgroup的onInterceptTouchEvent方法。

情况1,viewgroup1层onInterceptTouchEvent返回值为true,事件传递在这一层终止,ontouchEvent也在这一层终止。

12-30 12:38:13.655 21700-21700/com.kv.mymeet E/xx: act dispatchTouchEvent
12-30 12:38:13.656 21700-21700/com.kv.mymeet E/xx: vp1 dispatchTouchEvent
12-30 12:38:13.656 21700-21700/com.kv.mymeet E/xx: vp1 onInterceptTouchEvent
12-30 12:38:13.656 21700-21700/com.kv.mymeet E/xx: vp1 onTouchEvent
12-30 12:38:13.657 21700-21700/com.kv.mymeet E/xx: act onTouchEvent

情况2,viewgroup1层onInterceptTouchEvent返回值为false,事件传递正常,ontouchEvent也正常传递。

12-30 12:40:48.535 21700-21700/com.kv.mymeet E/xx: act dispatchTouchEvent
12-30 12:40:48.535 21700-21700/com.kv.mymeet E/xx: vp1 dispatchTouchEvent
12-30 12:40:48.536 21700-21700/com.kv.mymeet E/xx: vp1 onInterceptTouchEvent
12-30 12:40:48.536 21700-21700/com.kv.mymeet E/xx: vp2 dispatchTouchEvent
12-30 12:40:48.536 21700-21700/com.kv.mymeet E/xx: vp2 onInterceptTouchEvent
12-30 12:40:48.536 21700-21700/com.kv.mymeet E/xx: mv dispatchTouchEvent
12-30 12:40:48.536 21700-21700/com.kv.mymeet E/xx: mv onTouchEvent
12-30 12:40:48.537 21700-21700/com.kv.mymeet E/xx: vp2 onTouchEvent
12-30 12:40:48.537 21700-21700/com.kv.mymeet E/xx: vp1 onTouchEvent
12-30 12:40:48.538 21700-21700/com.kv.mymeet E/xx: act onTouchEvent
情况3, viewgroup2层onInterceptTouchEvent返回值为true,事件传递在这一层终止,ontouchEvent也在这一层终止。(想让父容器的子view不触发事件,可设onInterceptTouchEvent返回值为true
12-30 12:42:37.399 22347-22347/com.kv.mymeet E/xx: act dispatchTouchEvent
12-30 12:42:37.399 22347-22347/com.kv.mymeet E/xx: vp1 dispatchTouchEvent
12-30 12:42:37.399 22347-22347/com.kv.mymeet E/xx: vp1 onInterceptTouchEvent
12-30 12:42:37.399 22347-22347/com.kv.mymeet E/xx: vp2 dispatchTouchEvent
12-30 12:42:37.399 22347-22347/com.kv.mymeet E/xx: vp2 onInterceptTouchEvent
12-30 12:42:37.400 22347-22347/com.kv.mymeet E/xx: vp2 onTouchEvent
12-30 12:42:37.400 22347-22347/com.kv.mymeet E/xx: vp1 onTouchEvent
12-30 12:42:37.400 22347-22347/com.kv.mymeet E/xx: act onTouchEvent
3. 下面我们来操作viewgroup的onTouchEvent方法。

情况1,view层,设置onTouchEvent值为true,事件在这一层被消费,不向上传递。

12-30 12:51:24.742 23131-23131/com.kv.mymeet E/xx: act dispatchTouchEvent
12-30 12:51:24.742 23131-23131/com.kv.mymeet E/xx: vp1 dispatchTouchEvent
12-30 12:51:24.743 23131-23131/com.kv.mymeet E/xx: vp1 onInterceptTouchEvent
12-30 12:51:24.743 23131-23131/com.kv.mymeet E/xx: vp2 dispatchTouchEvent
12-30 12:51:24.743 23131-23131/com.kv.mymeet E/xx: vp2 onInterceptTouchEvent
12-30 12:51:24.743 23131-23131/com.kv.mymeet E/xx: mv dispatchTouchEvent
12-30 12:51:24.743 23131-23131/com.kv.mymeet E/xx: mv onTouchEvent

情况2,view层,设置onTouchEvent值为false,事件传递正常,ontouchEvent也正常传递。

12-30 12:54:38.713 23959-23959/com.kv.mymeet E/xx: act dispatchTouchEvent
12-30 12:54:38.714 23959-23959/com.kv.mymeet E/xx: vp1 dispatchTouchEvent
12-30 12:54:38.715 23959-23959/com.kv.mymeet E/xx: vp1 onInterceptTouchEvent
12-30 12:54:38.715 23959-23959/com.kv.mymeet E/xx: vp2 dispatchTouchEvent
12-30 12:54:38.715 23959-23959/com.kv.mymeet E/xx: vp2 onInterceptTouchEvent
12-30 12:54:38.715 23959-23959/com.kv.mymeet E/xx: mv dispatchTouchEvent
12-30 12:54:38.715 23959-23959/com.kv.mymeet E/xx: mv onTouchEvent
12-30 12:54:38.717 23959-23959/com.kv.mymeet E/xx: vp2 onTouchEvent
12-30 12:54:38.717 23959-23959/com.kv.mymeet E/xx: vp1 onTouchEvent
12-30 12:54:38.718 23959-23959/com.kv.mymeet E/xx: act onTouchEvent
情况3,viewgroup层,设置onTouchEvent值为true,事件在这一层被消费,不向上传递。
12-30 12:55:46.054 24256-24256/com.kv.mymeet E/xx: act dispatchTouchEvent
12-30 12:55:46.055 24256-24256/com.kv.mymeet E/xx: vp1 dispatchTouchEvent
12-30 12:55:46.055 24256-24256/com.kv.mymeet E/xx: vp1 onInterceptTouchEvent
12-30 12:55:46.055 24256-24256/com.kv.mymeet E/xx: vp2 dispatchTouchEvent
12-30 12:55:46.055 24256-24256/com.kv.mymeet E/xx: vp2 onInterceptTouchEvent
12-30 12:55:46.055 24256-24256/com.kv.mymeet E/xx: mv dispatchTouchEvent
12-30 12:55:46.056 24256-24256/com.kv.mymeet E/xx: mv onTouchEvent
12-30 12:55:46.056 24256-24256/com.kv.mymeet E/xx: vp2 onTouchEvent
情况4,viewgroup层,设置onTouchEvent值为false,事件传递正常,ontouchEvent也正常传递。
12-30 12:58:36.758 24256-24256/com.kv.mymeet E/xx: act dispatchTouchEvent
12-30 12:58:36.759 24256-24256/com.kv.mymeet E/xx: vp1 dispatchTouchEvent
12-30 12:58:36.759 24256-24256/com.kv.mymeet E/xx: vp1 onInterceptTouchEvent
12-30 12:58:36.759 24256-24256/com.kv.mymeet E/xx: vp2 dispatchTouchEvent
12-30 12:58:36.760 24256-24256/com.kv.mymeet E/xx: vp2 onInterceptTouchEvent
12-30 12:58:36.774 24256-24256/com.kv.mymeet E/xx: mv dispatchTouchEvent
12-30 12:58:36.774 24256-24256/com.kv.mymeet E/xx: mv onTouchEvent
12-30 12:58:36.775 24256-24256/com.kv.mymeet E/xx: vp2 onTouchEvent
12-30 12:58:36.775 24256-24256/com.kv.mymeet E/xx: vp1 onTouchEvent
12-30 12:58:36.776 24256-24256/com.kv.mymeet E/xx: act onTouchEvent

以上的试验,可以用画图直观的表现出来。




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值