事件传递

本文详细解析了Android中事件的传递与处理流程,包括ViewGroup的事件拦截机制及子View如何接收事件。通过具体代码示例展示了不同层级View间的交互过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    //ViewGroup的事件处理
    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        boolean consume = false;

        if (onInterceptTouchEvent(event)) {//ViewGroup拦截(viewgroup默认不拦截)
            consume = onTouchEvent(event);//则ViewGroup处理事件
        } else {//ViewGroup不拦截
            consume = child.dispatchTouchEvent(event);//则子view派发事件
        }

        return consume;
    }

事件的传递:隧道式派发

先执行dispatchTouchEvent方法
再执行onInterceptTouchEvent方法(view无此方法)
true,拦截,不用派发给下级
false,不拦截,派发给下级

事件的处理:冒泡式消费

只执行onTouchEvent方法(view没有拦截方法,事件传递过来时一定会执行这个方法,当clickable和longclickable都为true时如button默认消费事件)
true,处理了,不用处理了
false,没处理,给上级处理

dispatchTouchEvent方法:事件传递到当前view,此方法一定会被调用,返回值受当前view的onTouchEvent和下级view的dispatchTouchEvent返回值影响。

最后一级view一定会调用onTouchEvent方法。

例子如下:

Markdown

MyView

public class MyView extends View {

    //处理事件
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.e("TouchEvent","MyView==onTouchEvent=="+super.onTouchEvent(event)+"=="
                +event.getAction()+"=="+System.currentTimeMillis());
        return super.onTouchEvent(event);
    }

    //派发事件
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        Log.e("TouchEvent","MyView==dispatchTouchEvent=="+super.onTouchEvent(ev)+"=="
                +ev.getAction()+"=="+System.currentTimeMillis());
        return super.dispatchTouchEvent(ev);
    }

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

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

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

}

ViewGroupA

public class ViewGroupA extends LinearLayout {

    //处理事件
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.e("TouchEvent","ViewGroupA==onTouchEvent=="+super.onTouchEvent(event)+"=="
                +event.getAction()+"=="+System.currentTimeMillis());
        return super.onTouchEvent(event);
    }

    //派发事件
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        Log.e("TouchEvent","ViewGroupA==dispatchTouchEvent=="+super.onTouchEvent(ev)+"=="
                +ev.getAction()+"=="+System.currentTimeMillis());
        return super.dispatchTouchEvent(ev);
    }

    //拦截事件
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        Log.e("TouchEvent","ViewGroupA==onInterceptTouchEvent=="+super.onTouchEvent(ev)+"=="
                +ev.getAction()+"=="+System.currentTimeMillis());
        return super.onInterceptTouchEvent(ev);
    }

    //构造方法
    public ViewGroupA(Context context) {
        super(context);
    }

    public ViewGroupA(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ViewGroupA(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

}

ViewGroupB

public class ViewGroupB extends LinearLayout {

    //处理事件
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.e("TouchEvent","ViewGroupB==onTouchEvent=="+super.onTouchEvent(event)+"=="
                +event.getAction()+"=="+System.currentTimeMillis());
        return super.onTouchEvent(event);
    }

    //派发事件
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        Log.e("TouchEvent","ViewGroupB==dispatchTouchEvent=="+super.onTouchEvent(ev)+"=="
                +ev.getAction()+"=="+System.currentTimeMillis());
        return super.dispatchTouchEvent(ev);
    }

    //拦截事件
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        Log.e("TouchEvent","ViewGroupB==onInterceptTouchEvent=="+super.onTouchEvent(ev)+"=="
                +ev.getAction()+"=="+System.currentTimeMillis());
        return super.onInterceptTouchEvent(ev);
    }

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

    public ViewGroupB(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ViewGroupB(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }


}

布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.administrator.myapplication.MainActivity">

    <com.example.administrator.myapplication.ViewGroupA
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/holo_blue_bright">

        <com.example.administrator.myapplication.ViewGroupB
            android:layout_width="300dp"
            android:layout_height="300dp"
            android:background="@android:color/holo_green_dark">

            <com.example.administrator.myapplication.MyView
                android:layout_width="150dp"
                android:layout_height="150dp"
                android:background="@android:color/darker_gray" />
        </com.example.administrator.myapplication.ViewGroupB>
    </com.example.administrator.myapplication.ViewGroupA>

</RelativeLayout>

点击ViewGroupA

02-06 11:48:55.295 10298-10298/? E/TouchEvent: 
ViewGroupA==dispatchTouchEvent==false==0==1486352935295
02-06 11:48:55.295 10298-10298/? E/TouchEvent: 
ViewGroupA==onInterceptTouchEvent==false==0==1486352935295
02-06 11:48:55.295 10298-10298/? E/TouchEvent: 
ViewGroupA==onTouchEvent==false==0==1486352935295

点击ViewGroupB

02-06 11:47:40.835 10298-10298/? E/TouchEvent: 
ViewGroupA==dispatchTouchEvent==false==0==1486352860834
02-06 11:47:40.835 10298-10298/? E/TouchEvent: 
ViewGroupA==onInterceptTouchEvent==false==0==1486352860835

02-06 11:47:40.835 10298-10298/? E/TouchEvent: 
ViewGroupB==dispatchTouchEvent==false==0==1486352860835
02-06 11:47:40.835 10298-10298/? E/TouchEvent: 
ViewGroupB==onInterceptTouchEvent==false==0==1486352860835
02-06 11:47:40.835 10298-10298/? E/TouchEvent: 
ViewGroupB==onTouchEvent==false==0==1486352860835

02-06 11:47:40.835 10298-10298/? E/TouchEvent: 
ViewGroupA==onTouchEvent==false==0==1486352860835

点击MyView

02-06 11:45:01.557 10298-10298/? E/TouchEvent: 
ViewGroupA==dispatchTouchEvent==false==0==1486352701556
02-06 11:45:01.557 10298-10298/? E/TouchEvent: 
ViewGroupA==onInterceptTouchEvent==false==0==1486352701557

02-06 11:45:01.557 10298-10298/? E/TouchEvent: 
ViewGroupB==dispatchTouchEvent==false==0==1486352701557
02-06 11:45:01.557 10298-10298/? E/TouchEvent: 
ViewGroupB==onInterceptTouchEvent==false==0==1486352701557

02-06 11:45:01.557 10298-10298/? E/TouchEvent:
MyView==dispatchTouchEvent==false==0==1486352701557
02-06 11:45:01.557 10298-10298/? E/TouchEvent: 
MyView==onTouchEvent==false==0==1486352701557

02-06 11:45:01.562 10298-10298/? E/TouchEvent:
ViewGroupB==onTouchEvent==false==0==1486352701562

02-06 11:45:01.562 10298-10298/? E/TouchEvent: 
ViewGroupA==onTouchEvent==false==0==1486352701562

参考:

Android艺术探索
Android群英传

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值