Android事件分发机制之ViewGroup篇

本文通过一个简单的Demo深入解析了Android的事件分发机制,包括Activity、ViewGroup及View的dispatchTouchEvent、onInterceptTouchEvent和onTouchEvent等关键方法的调用流程。

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

上一篇我们介绍了Android事件分发机制之View篇,相信大家对Android的事件分发有了一定的了解!在讲之前我们要明确两个概念:一个是View,一个是ViewGroup。当然ViewGroup是个容器,它的父类是View,它也包含很多子View和ViewGroup。好了,我们进入本文正题吧!

首先我们提供一个Demo的效果图:
这里写图片描述
该效果图的界面非常简单,界面中只有一个按钮。

一、layout文件

activity_main.xml文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <cn.ithm.eventdemo.MyLayout
        android:id="@+id/mylayout"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:gravity="center" >

        <cn.ithm.eventdemo.MyButton
            android:id="@+id/mybutton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/hello_world" />
    </cn.ithm.eventdemo.MyLayout>

</LinearLayout>

二、主要类文件

1.MyButton.java类

public class MyButton extends Button {

    private static final String TAG = "MyButton";

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

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {

        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            Log.i(TAG, "MyButton dispatchTouchEvent--ACTION_DOWN");
            break;
        case MotionEvent.ACTION_UP:
            Log.i(TAG, "MyButton dispatchTouchEvent--ACTION_UP");

            break;

        default:
            break;
        }
        return super.dispatchTouchEvent(event);
//      return true;
    }



    @Override
    public boolean onTouchEvent(MotionEvent event) {

        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            Log.i(TAG, "MyButton onTouchEvent--ACTION_DOWN");

            break;
        case MotionEvent.ACTION_UP:
            Log.i(TAG, "MyButton onTouchEvent--ACTION_UP");

            break;

        default:
            break;
        }
        return super.onTouchEvent(event);
    }

}

2.MyLayout.java类

public class MyLayout extends LinearLayout {

    private static final String TAG = "MyLayout";

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

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {

        switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN:
            Log.i(TAG, "MyLayout dispatchTouchEvent--ACTION_DOWN");
            break;
        case MotionEvent.ACTION_UP:
            Log.i(TAG, "MyLayout dispatchTouchEvent--ACTION_UP");

            break;

        default:
            break;
        }
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN:
            Log.i(TAG, "MyLayout onInterceptTouchEvent--ACTION_DOWN");
            break;
        case MotionEvent.ACTION_UP:
            Log.i(TAG, "MyLayout onInterceptTouchEvent--ACTION_UP");

            break;

        default:
            break;
        }
        return super.onInterceptTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            Log.i(TAG, "MyLayout onTouchEvent--ACTION_DOWN");
            break;
        case MotionEvent.ACTION_UP:
            Log.i(TAG, "MyLayout onTouchEvent--ACTION_UP");

            break;

        default:
            break;
        }
        return super.onTouchEvent(event);
    }

}

3.MainActivity.java类

public class MainActivity extends Activity {

    protected static final String TAG = "MainActivity";
    private Button button;
    private LinearLayout myLayout;

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

        button = (Button) findViewById(R.id.mybutton);
        myLayout = (LinearLayout) findViewById(R.id.mylayout);

        button.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {
                Log.i(TAG, "MyButton onclick");
            }
        });

        button.setOnTouchListener(new OnTouchListener() {

            @Override
            public boolean onTouch(View arg0, MotionEvent arg1) {
                switch (arg1.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    Log.i(TAG, "MyButton setOnTouchListener--ACTION_DOWN");

                    break;
                case MotionEvent.ACTION_UP:

                    Log.i(TAG, "MyButton setOnTouchListener--ACTION_UP");
                    break;

                default:
                    break;
                }

                return false;
            }
        });

        myLayout.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {

                Log.i(TAG, "myLayout onclick");
            }
        });

        myLayout.setOnTouchListener(new OnTouchListener() {

            @Override
            public boolean onTouch(View arg0, MotionEvent arg1) {
                switch (arg1.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    Log.i(TAG, "myLayout setOnTouchListener--ACTION_DOWN");

                    break;
                case MotionEvent.ACTION_UP:

                    Log.i(TAG, "myLayout setOnTouchListener--ACTION_UP");
                    break;

                default:
                    break;
                }

                return false;
            }
        });
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {

        switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN:
            Log.i(TAG, "MainActivity dispatchTouchEvent--ACTION_DOWN");
            break;
        case MotionEvent.ACTION_UP:
            Log.i(TAG, "MainActivity dispatchTouchEvent--ACTION_UP");
            break;

        default:
            break;
        }
        return super.dispatchTouchEvent(ev);
        // return true;
    }

}

三、分析事件分发过程

1、首先我们点击“事件分发”按钮,查看LogCat,其打印结果为:
这里写图片描述
我们发现它的分发顺序为:Activity的dispatchTouchEvent方法->ViewGroup的dispatchTouchEvent方法->ViewGroup的onInterceptTouchEvent的方法->子View的dispatchTouchEvent方法->子View的onTouch的方法->子View的onTouchEvent的方法,然后是up,这个跟down是相同的。最后是子view的onClick事件。
2.然后我们点击界面空白处,查看LogCat,其打印结果为:
这里写图片描述
我们发现它的分发顺序为:Activity的dispatchTouchEvent方法->ViewGroup的dispatchTouchEvent方法->ViewGroup的onInterceptTouchEvent的方法->ViewGroup的onTouch的方法->ViewGroup的onTouchEvent的方法,然后是up,这个跟down是相同的。最后是ViewGroup的onClick事件。

四、总结

1、其实ViewGroup的事件分发就是比View的多了一个方法onInterceptTouchEvent,为什么会多这样一个方法呢?主要是因为ViewGroup有子View,而View是没有子view的。
2、同理,ViewGroup的事件分发在某个点被消耗了,它也不会继续往下转发下去。

最后,Android的事件分发就简单粗略的讲完了,相信读者应该有个大致的认识了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值