欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android 事件传递机制实测

程序员文章站 2022-07-14 21:57:53
...

一,这个一直不懂,着实不是办法。看了几篇文章。顺便实操下、

初识Android触摸事件传递机制

事件传递三个阶段
分发(Dispatch):事件的分发对应着dispatchTouchEvent方法,在Andorid系统中,所有的触摸事件都是通过这个方法来分发的。

boolean dispatchTouchEvent (MotionEvent ev)
这个方法中,可以决定直接消费这个事件或者将事件继续分发给子视图处理。

拦截(Intercept):事件拦截对应着onInterceptTouchEvent方法,这个方法只有在ViewGroup及其子类中才存在,在View和Activity中是不存在的。

boolean onInterceptTouchEvent (MotionEvent ev)
这个方法用来判断是否拦截某个事件,如果拦截了某个事件,那么在同一序列事件当中,那么这个方法不会被再次调用。

消费(Consume):事件消费对应着onTouchEvent方法。

boolean onTouchEvent (MotionEvent event)
用来处理点击事件,返回结果表示是否消耗当前事件,如果不消耗,则在同一事件序列中,当前View无法再接收到事件

在Android系统中,拥有事件传递处理能力的有三种:

Activity:拥有dispatchTouchEvent、onTouchEvent两个方法。
ViewGroup:拥有dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent三个方法。
View:拥有dispatchTouchEvent、onTouchEvent两个方法。

View事件传递机制
这里说的View指的是除了ViewGroup之外的View控件,比如TextView、Button、CheckBox等,View控件本身就是最小的单位,不能作为其他View的容器,View拥有dispatchTouchEvent、onTouchEvent两个方法,所以这里就定义了一个继承TextView的类MyTextView,通过代码查看日志,看流程如何走。

单纯的没有组合控件 或则自定义控件代码情况如下:

package com.cwj.twoday;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    Button btn;
    MyTextView tv;
    MyRelativeLayout mylayout;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn = findViewById(R.id.btn);
        tv = findViewById(R.id.my_tv);
        mylayout = findViewById(R.id.mylayout);
        btn.setOnClickListener(this);
        tv.setOnClickListener(this);
        mylayout.setOnClickListener(this);
    }
    //事件分发
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN://按下
                Log.e("dispatchTouchEvent-分发", "按下");
                break;
            case MotionEvent.ACTION_MOVE://触摸
                Log.e("dispatchTouchEvent-分发", "触摸");
                break;
            case MotionEvent.ACTION_UP://松开
                Log.e("dispatchTouchEvent-分发", "松开");
                break;
            case MotionEvent.ACTION_CANCEL://取消
                Log.e("dispatchTouchEvent-分发", "取消");
                break;
        }
        return super.dispatchTouchEvent(ev);
    }
    //触摸事件
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN://按下
                Log.e("onTouchEvent", "按下");
                break;
            case MotionEvent.ACTION_MOVE://触摸
                Log.e("onTouchEvent", "触摸");
                break;
            case MotionEvent.ACTION_UP://松开
                Log.e("onTouchEvent", "松开");
                break;
            case MotionEvent.ACTION_CANCEL://取消
                Log.e("onTouchEvent", "取消");
                break;
        }
        return super.onTouchEvent(event);
    }
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN://按下
                Log.e("onKeyDown", "按下");
                break;
            case MotionEvent.ACTION_MOVE://触摸
                Log.e("onKeyDown", "触摸");
                break;
            case MotionEvent.ACTION_UP://松开
                Log.e("onKeyDown", "松开");
                break;
            case MotionEvent.ACTION_CANCEL://取消
                Log.e("onKeyDown", "取消");
                break;
        }

        return super.onKeyDown(keyCode, event);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn:
                break;
                case R.id.my_tv:
                break;
                case R.id.mylayout:

                break;
        }
    }

}


单纯点击屏幕,这里没有点击Button

2019-03-14 17:46:24.163 6394-6394/com.cwj.twoday E/dispatchTouchEvent-分发: 按下
2019-03-14 17:46:24.164 6394-6394/com.cwj.twoday E/onTouchEvent: 按下
2019-03-14 17:46:24.227 6394-6394/com.cwj.twoday E/dispatchTouchEvent-分发: 松开
2019-03-14 17:46:24.227 6394-6394/com.cwj.twoday E/onTouchEvent: 松开

触摸就会触发触摸事件

2019-03-14 17:46:44.757 6394-6394/com.cwj.twoday E/dispatchTouchEvent-分发: 按下
2019-03-14 17:46:44.758 6394-6394/com.cwj.twoday E/onTouchEvent: 按下
2019-03-14 17:46:44.852 6394-6394/com.cwj.twoday E/dispatchTouchEvent-分发: 触摸
2019-03-14 17:46:44.853 6394-6394/com.cwj.twoday E/onTouchEvent: 触摸
2019-03-14 17:46:44.873 6394-6394/com.cwj.twoday E/dispatchTouchEvent-分发: 触摸
2019-03-14 17:46:44.873 6394-6394/com.cwj.twoday E/onTouchEvent: 触摸
2019-03-14 17:46:44.880 6394-6394/com.cwj.twoday E/dispatchTouchEvent-分发: 触摸
2019-03-14 17:46:44.880 6394-6394/com.cwj.twoday E/onTouchEvent: 触摸
2019-03-14 17:46:44.880 6394-6394/com.cwj.twoday E/dispatchTouchEvent-分发: 松开
2019-03-14 17:46:44.881 6394-6394/com.cwj.twoday E/onTouchEvent: 松开

执行顺序:dispatchTouchEvent→onTouchEvent

第二个:View的触发事件 测试通过View来触发触摸事件。如下

 package com.cwj.twoday;

import android.annotation.SuppressLint;
import android.content.Context;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.TextView;

/**
 * Created by CWJ on 2019/3/14.
 * Author:Chen
 * Email:[email protected]
 * Ver:1
 * DEC:View事件传递机制
 */
@SuppressLint("AppCompatCustomView")
public class MyTextView extends TextView {
    public MyTextView(Context context) {
        super(context);
    }

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

    @SuppressLint("LongLogTag")
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN://按下
                Log.e("View-dispatchTouchEvent分发", "按下");
                break;
            case MotionEvent.ACTION_MOVE://触摸
                Log.e("View-dispatchTouchEvent分发", "触摸");
                break;
            case MotionEvent.ACTION_UP://松开
                Log.e("View-dispatchTouchEvent分发", "松开");
                break;
            case MotionEvent.ACTION_CANCEL://取消
                Log.e("View-dispatchTouchEvent分发", "取消");
                break;
        }
        return super.dispatchTouchEvent(ev);
    }

    //触摸事件
    @SuppressLint("LongLogTag")
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN://按下
                Log.e("View-onTouchEvent触摸", "按下");
                break;
            case MotionEvent.ACTION_MOVE://触摸
                Log.e("View-onTouchEvent触摸", "触摸");
                break;
            case MotionEvent.ACTION_UP://松开
                Log.e("View-onTouchEvent触摸", "松开");
                break;
            case MotionEvent.ACTION_CANCEL://取消
                Log.e("View-onTouchEvent触摸", "取消");
                break;
        }
        return super.onTouchEvent(event);
    }
}

 

结果如下:

2019-03-14 17:48:19.869 6394-6394/com.cwj.twoday E/dispatchTouchEvent-分发: 按下
2019-03-14 17:48:19.870 6394-6394/com.cwj.twoday E/View-dispatchTouchEvent分发: 按下
2019-03-14 17:48:19.871 6394-6394/com.cwj.twoday E/View-onTouchEvent触摸: 按下
2019-03-14 17:48:19.985 6394-6394/com.cwj.twoday E/dispatchTouchEvent-分发: 触摸
2019-03-14 17:48:19.986 6394-6394/com.cwj.twoday E/View-dispatchTouchEvent分发: 触摸
2019-03-14 17:48:19.986 6394-6394/com.cwj.twoday E/View-onTouchEvent触摸: 触摸
2019-03-14 17:48:19.986 6394-6394/com.cwj.twoday E/dispatchTouchEvent-分发: 松开
2019-03-14 17:48:19.987 6394-6394/com.cwj.twoday E/View-dispatchTouchEvent分发: 松开
2019-03-14 17:48:19.987 6394-6394/com.cwj.twoday E/View-onTouchEvent触摸: 松开

执行顺序 :父布局.dispatchTouchEvent→View.dispatchTouchEvent→View.onTouchEvent

最后ViewGroup 的触发事件

package com.cwj.twoday;

import android.annotation.SuppressLint;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.RelativeLayout;

/**
 * Created by CWJ on 2019/3/14.
 * Author:Chen
 * Email:[email protected]
 * Ver:1
 * DEC:ViewGroup事件传递机制
 */
@SuppressLint("LongLogTag")

public class MyRelativeLayout extends RelativeLayout {


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

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

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN://按下
                Log.e("ViewGroup-dispatchTouchEvent分发", "按下");
                break;
            case MotionEvent.ACTION_MOVE://触摸
                Log.e("ViewGroup-dispatchTouchEvent分发", "触摸");
                break;
            case MotionEvent.ACTION_UP://松开
                Log.e("ViewGroup-dispatchTouchEvent分发", "松开");
                break;
            case MotionEvent.ACTION_CANCEL://取消
                Log.e("ViewGroup-dispatchTouchEvent分发", "取消");
                break;
        }
        return super.dispatchTouchEvent(ev);
    }

    //触摸事件
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN://按下
                Log.e("ViewGroup-onTouchEvent触摸", "按下");
                break;
            case MotionEvent.ACTION_MOVE://触摸
                Log.e("ViewGroup-onTouchEvent触摸", "触摸");
                break;
            case MotionEvent.ACTION_UP://松开
                Log.e("ViewGroup-onTouchEvent触摸", "松开");
                break;
            case MotionEvent.ACTION_CANCEL://取消
                Log.e("ViewGroup-onTouchEvent触摸", "取消");
                break;
        }
        return super.onTouchEvent(event);
    }


    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN://按下
                Log.e("ViewGroup-onInterceptTouchEvent", "按下");
                break;
            case MotionEvent.ACTION_MOVE://触摸
                Log.e("ViewGroup-onInterceptTouchEvent", "触摸");
                break;
            case MotionEvent.ACTION_UP://松开
                Log.e("ViewGroup-onInterceptTouchEvent", "松开");
                break;
            case MotionEvent.ACTION_CANCEL://取消
                Log.e("ViewGroup-onInterceptTouchEvent", "取消");
                break;
        }
        return super.onInterceptTouchEvent(ev);
    }
}

结果如下:

2019-03-14 17:48:52.303 6394-6394/com.cwj.twoday E/dispatchTouchEvent-分发: 按下
2019-03-14 17:48:52.303 6394-6394/com.cwj.twoday E/ViewGroup-dispatchTouchEvent分发: 按下
2019-03-14 17:48:52.304 6394-6394/com.cwj.twoday E/ViewGroup-onInterceptTouchEvent: 按下
2019-03-14 17:48:52.304 6394-6394/com.cwj.twoday E/ViewGroup-onTouchEvent触摸: 按下
2019-03-14 17:48:52.379 6394-6394/com.cwj.twoday E/dispatchTouchEvent-分发: 松开
2019-03-14 17:48:52.379 6394-6394/com.cwj.twoday E/ViewGroup-dispatchTouchEvent分发: 松开
2019-03-14 17:48:52.379 6394-6394/com.cwj.twoday E/ViewGroup-onTouchEvent触摸: 松开

执行顺序:父布局:dispatchTouchEvent→ViewGroup.dispatchTouchEvent→ViewGroup.onInterceptTouchEvent→ViewGroup.onTouchEvent

感谢这位大神 初识Android触摸事件传递机制
敲一遍。是对好的老师。