Android事件传递简单分析

1.Activity事件处理

package com.example.eventdemo01;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.MotionEvent;

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "xtm";

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

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        DebugUtils.printLogD(TAG,"Activity dispatchTouchEvent.");
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        DebugUtils.printLogD(TAG,"Activity onTouchEvent.");
        return super.onTouchEvent(event);
    }

}

按下:会回调一次dispatchTouchEvent,onTouchEvent

移动:多次回调dispatchTouchEvent,onTouchEvent

抬起:会回调一次dispatchTouchEvent,onTouchEvent

相关日志:

// 按下
2020-12-28 09:51:49.210 17300-17300/com.example.eventdemo01 D/xtm: Activity dispatchTouchEvent.
2020-12-28 09:51:49.210 17300-17300/com.example.eventdemo01 D/xtm: Activity onTouchEvent.
// 移动
2020-12-28 09:51:49.848 17300-17300/com.example.eventdemo01 D/xtm: Activity dispatchTouchEvent.
2020-12-28 09:51:49.848 17300-17300/com.example.eventdemo01 D/xtm: Activity onTouchEvent.
2020-12-28 09:51:49.865 17300-17300/com.example.eventdemo01 D/xtm: Activity dispatchTouchEvent.
2020-12-28 09:51:49.865 17300-17300/com.example.eventdemo01 D/xtm: Activity onTouchEvent.
2020-12-28 09:51:49.881 17300-17300/com.example.eventdemo01 D/xtm: Activity dispatchTouchEvent.
2020-12-28 09:51:49.881 17300-17300/com.example.eventdemo01 D/xtm: Activity onTouchEvent.
2020-12-28 09:51:49.897 17300-17300/com.example.eventdemo01 D/xtm: Activity dispatchTouchEvent.
2020-12-28 09:51:49.898 17300-17300/com.example.eventdemo01 D/xtm: Activity onTouchEvent.
2020-12-28 09:51:49.915 17300-17300/com.example.eventdemo01 D/xtm: Activity dispatchTouchEvent.
2020-12-28 09:51:49.915 17300-17300/com.example.eventdemo01 D/xtm: Activity onTouchEvent.
2020-12-28 09:51:49.932 17300-17300/com.example.eventdemo01 D/xtm: Activity dispatchTouchEvent.
2020-12-28 09:51:49.932 17300-17300/com.example.eventdemo01 D/xtm: Activity onTouchEvent.
2020-12-28 09:51:49.948 17300-17300/com.example.eventdemo01 D/xtm: Activity dispatchTouchEvent.
2020-12-28 09:51:49.948 17300-17300/com.example.eventdemo01 D/xtm: Activity onTouchEvent.
// 抬起
2020-12-28 09:51:50.962 17300-17300/com.example.eventdemo01 D/xtm: Activity dispatchTouchEvent.
2020-12-28 09:51:50.962 17300-17300/com.example.eventdemo01 D/xtm: Activity onTouchEvent.

2.ViewGroup事件处理

自定义一个ViewGroup

package com.example.eventdemo01;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.LinearLayout;

public class MyViewGroup extends LinearLayout {
    private static final String TAG = "xtm";

    public MyViewGroup(Context context, AttributeSet attrs) {
        super(context, attrs);

    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        DebugUtils.printLogD(TAG,"MyViewGroup dispatchTouchEvent.");
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        DebugUtils.printLogD(TAG,"MyViewGroup onInterceptTouchEvent.");
        return super.onInterceptTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        boolean isConsume = super.onTouchEvent(ev);
        DebugUtils.printLogD(TAG,"MyViewGroup onTouchEvent. isConsume:"+isConsume);
        return isConsume;
    }
}

布局:

<?xml version="1.0" encoding="utf-8"?>
<com.example.eventdemo01.MyViewGroup xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
</com.example.eventdemo01.MyViewGroup>

点击一次的打印:

// 按下
2020-12-28 14:25:33.741 7326-7326/com.example.eventdemo01 D/xtm: Activity dispatchTouchEvent.
2020-12-28 14:25:33.741 7326-7326/com.example.eventdemo01 D/xtm: MyViewGroup dispatchTouchEvent.
2020-12-28 14:25:33.741 7326-7326/com.example.eventdemo01 D/xtm: MyViewGroup onInterceptTouchEvent.
2020-12-28 14:25:33.741 7326-7326/com.example.eventdemo01 D/xtm: MyViewGroup onTouchEvent. isConsume:false
2020-12-28 14:25:33.741 7326-7326/com.example.eventdemo01 D/xtm: Activity onTouchEvent.
// 移动
2020-12-28 14:25:34.948 7326-7326/com.example.eventdemo01 D/xtm: Activity dispatchTouchEvent.
2020-12-28 14:25:34.948 7326-7326/com.example.eventdemo01 D/xtm: Activity onTouchEvent.
2020-12-28 14:25:34.963 7326-7326/com.example.eventdemo01 D/xtm: Activity dispatchTouchEvent.
2020-12-28 14:25:34.963 7326-7326/com.example.eventdemo01 D/xtm: Activity onTouchEvent.
2020-12-28 14:25:34.980 7326-7326/com.example.eventdemo01 D/xtm: Activity dispatchTouchEvent.
2020-12-28 14:25:34.980 7326-7326/com.example.eventdemo01 D/xtm: Activity onTouchEvent.
2020-12-28 14:25:35.097 7326-7326/com.example.eventdemo01 D/xtm: Activity dispatchTouchEvent.
2020-12-28 14:25:35.097 7326-7326/com.example.eventdemo01 D/xtm: Activity onTouchEvent.
// 抬起
2020-12-28 14:25:36.269 7326-7326/com.example.eventdemo01 D/xtm: Activity dispatchTouchEvent.
2020-12-28 14:25:36.269 7326-7326/com.example.eventdemo01 D/xtm: Activity onTouchEvent.

3.View事件处理

父亲布局:

package com.example.eventdemo01;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.LinearLayout;

public class MyViewGroup extends LinearLayout {
    private static final String TAG = "xtm";

    public MyViewGroup(Context context, AttributeSet attrs) {
        super(context, attrs);

    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        DebugUtils.printLogD(TAG,"MyViewGroup dispatchTouchEvent.");
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        DebugUtils.printLogD(TAG,"MyViewGroup onInterceptTouchEvent.");
        return super.onInterceptTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        boolean isConsume = super.onTouchEvent(ev);
        DebugUtils.printLogD(TAG,"MyViewGroup onTouchEvent. isConsume:"+isConsume);
        return isConsume;
    }
}

子布局

package com.example.eventdemo01;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.LinearLayout;

import androidx.annotation.Nullable;

public class MyLinearLayout extends LinearLayout {
    private static final String TAG = "xtm";
    public MyLinearLayout(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        DebugUtils.printLogD(TAG,"MyLinearLayout dispatchTouchEvent.");
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        DebugUtils.printLogD(TAG,"MyLinearLayout onInterceptTouchEvent.");
        return false;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        boolean isConsume = super.onTouchEvent(ev);
        DebugUtils.printLogD(TAG,"MyLinearLayout onTouchEvent. isConsume:"+isConsume);
        return isConsume;
    }
}

子布局嵌套一个View

package com.example.eventdemo01;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;

import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatImageView;

public class MyImageView extends AppCompatImageView {
    private static final String TAG = "xtm";
    public MyImageView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        DebugUtils.printLogD(TAG,"MyImageView dispatchTouchEvent.");
        return super.dispatchTouchEvent(event);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        boolean isConsume = super.onTouchEvent(event);
        DebugUtils.printLogD(TAG,"MyImageView onTouchEvent. isConsume:"+isConsume);
        return isConsume;
    }

}

布局:

<?xml version="1.0" encoding="utf-8"?>
<com.example.eventdemo01.MyViewGroup xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <com.example.eventdemo01.MyLinearLayout
        android:background="#00BCD4"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
       <com.example.eventdemo01.MyImageView
            android:layout_gravity="center"
            android:background="#f0f"
            android:layout_width="300dp"
            android:layout_height="300dp"/>
    </com.example.eventdemo01.MyLinearLayout>


</com.example.eventdemo01.MyViewGroup>

按下抬起后打印:

// 按下
2020-12-28 14:28:49.661 8586-8586/com.example.eventdemo01 D/xtm: Activity dispatchTouchEvent.
2020-12-28 14:28:49.661 8586-8586/com.example.eventdemo01 D/xtm: MyViewGroup dispatchTouchEvent.
2020-12-28 14:28:49.661 8586-8586/com.example.eventdemo01 D/xtm: MyViewGroup onInterceptTouchEvent.
2020-12-28 14:28:49.661 8586-8586/com.example.eventdemo01 D/xtm: MyLinearLayout dispatchTouchEvent.
2020-12-28 14:28:49.661 8586-8586/com.example.eventdemo01 D/xtm: MyLinearLayout onInterceptTouchEvent.
2020-12-28 14:28:49.661 8586-8586/com.example.eventdemo01 D/xtm: MyImageView dispatchTouchEvent.
2020-12-28 14:28:49.661 8586-8586/com.example.eventdemo01 D/xtm: MyImageView onTouchEvent. isConsume:false
2020-12-28 14:28:49.661 8586-8586/com.example.eventdemo01 D/xtm: MyLinearLayout onTouchEvent. isConsume:false
2020-12-28 14:28:49.661 8586-8586/com.example.eventdemo01 D/xtm: MyViewGroup onTouchEvent. isConsume:false
2020-12-28 14:28:49.661 8586-8586/com.example.eventdemo01 D/xtm: Activity onTouchEvent.
// 移动
2020-12-28 14:28:50.546 8586-8586/com.example.eventdemo01 D/xtm: Activity dispatchTouchEvent.
2020-12-28 14:28:50.546 8586-8586/com.example.eventdemo01 D/xtm: Activity onTouchEvent.
2020-12-28 14:28:50.563 8586-8586/com.example.eventdemo01 D/xtm: Activity dispatchTouchEvent.
2020-12-28 14:28:50.563 8586-8586/com.example.eventdemo01 D/xtm: Activity onTouchEvent.
2020-12-28 14:28:50.580 8586-8586/com.example.eventdemo01 D/xtm: Activity dispatchTouchEvent.
2020-12-28 14:28:50.580 8586-8586/com.example.eventdemo01 D/xtm: Activity onTouchEvent.
// 抬起
2020-12-28 14:28:51.229 8586-8586/com.example.eventdemo01 D/xtm: Activity dispatchTouchEvent.
2020-12-28 14:28:51.229 8586-8586/com.example.eventdemo01 D/xtm: Activity onTouchEvent.

观察设置MyLinearLayout的onInterceptTouchEvent和onTouchEvent的不同返回值的事件传递

按下移动并抬起MyImageView:

onInterceptTouchEvent

onTouchEvent

按下

移动

抬起

false

false

dispatchTouchEvent:Activity->MyViewGroup->MyLinearLayout->MyImageView

onTouchEvent:MyImageView->MyLinearLayout->ViewGroup->Actvity

dispatchTouchEvent: Activity

onTouchEvent:Activity

同移动

false

true

dispatchTouchEvent:Activity->MyViewGroup->MyLinearLayout->MyImageView

onTouchEvent:MyImageView->MyLinearLayout

dispatchTouchEvent: Activity->MyViewGroup->MyLinearLayout

onTouchEvent:MyLinearLayout

同移动

true

false

dispatchTouchEvent:Activity->MyViewGroup->MyLinearLayout

onTouchEvent:MyLinearLayout->ViewGroup->Actvity

dispatchTouchEvent: Activity

onTouchEvent: Activity

同移动

true

true

dispatchTouchEvent:Activity->MyViewGroup->MyLinearLayout

onTouchEvent:MyLinearLayout

dispatchTouchEvent: Activity->MyViewGroup->MyLinearLayout

onTouchEvent: MyLinearLayout

同移动

从上表看出:

1.移动事件主要看onTouchEvent的返回值,true表示所有移动事件都在这里处理,不再回传给父布局处理;false表示向父布局找一个返回true的布局,若没有的话就都交给了Activity处理。

2.onInterceptTouchEvent表示事件是否向下传递。

3.onTouchEvent表示事件最终由谁处理。

已获取焦点的子ViewGroup可以通过以下方法拦截事件:

/**
 * Called when a child does not want this parent and its ancestors to
 * intercept touch events with
 * {@link ViewGroup#onInterceptTouchEvent(MotionEvent)}.
 *
 * <p>This parent should pass this call onto its parents. This parent must obey
 * this request for the duration of the touch (that is, only clear the flag
 * after this parent has received an up or a cancel.</p>
 * 
 * @param disallowIntercept True if the child does not want the parent to
 *            intercept touch events.
 */
public void requestDisallowInterceptTouchEvent(boolean disallowIntercept);

猜你喜欢

转载自blog.csdn.net/qq_17441227/article/details/111867363