Android触摸事件传递机制(一)

简介: 在开发过程中会经常遇到View与ViewGroup嵌套的问题,如ViewPager嵌套Fragment,而Fragment中又需要实现一个广告滑动,此时广告滑动就会与ViewPager的滑动事件产生冲突,而深入理解Android触摸事件的传递机制则是解决问题的关键。

在开发过程中会经常遇到View与ViewGroup嵌套的问题,如ViewPager嵌套Fragment,而Fragment中又需要实现一个广告滑动,此时广告滑动就会与ViewPager的滑动事件产生冲突,而深入理解Android触摸事件的传递机制则是解决问题的关键。

一.触摸事件的类型(主要有三种)

1.MotionEvent.ACTION_DOWN:手指按下屏幕触发。
2.MotionEvent.ACTION_MOVE:手指在屏幕上移动触发。
3.MotionEvent.ACTION_UP:手指抬起时触发。

二.事件传递的三个阶段

1.方法介绍:

1).分发(DisPatch):对应的方法为:public boolean dispatchTouchEvent(MotionEvent ev),该方法的返回值决定了是否将事件向子视图传递:true:不传递;false:不传递;super.dispatchTouchEvent(ev):传递。
2).拦截(InterCept):对应的方法为:public boolean onInterceptTouchEvent(MotionEvent ev),该方法只有ViewGroup和其子类才有,该方法的返回值决定了是否拦截事件:true:拦截;false:不拦截;super.onInterceptTouchEvent(ev):不拦截。
3).消费(Consume):对应的方法为:public boolean onTouchEvent(MotionEvent event),该方法的返回值决定了是否处理该事件:true:处理;false:不处理;super.onTouchEvent(event):将会调用onClick()方法。

2.Activity与View事件传递演示

1).View代码(继承TextView重写onTouchEvent和dispatchTouchEvent方法)
public class MyTextView extends TextView {
    public MyTextView(Context context) {
        super(context);
    }

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

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

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                Log.e("MyTextView","onTouchEvent:ACTION_DOWN");
                break;
            case MotionEvent.ACTION_MOVE:
                Log.e("MyTextView","onTouchEvent:ACTION_MOVE");
                break;
            case MotionEvent.ACTION_UP:
                Log.e("MyTextView","onTouchEvent:ACTION_UP");
                break;
        }
        return super.onTouchEvent(event);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                Log.e("MyTextView","dispatchTouchEvent:ACTION_DOWN");
                break;
            case MotionEvent.ACTION_MOVE:
                Log.e("MyTextView","dispatchTouchEvent:ACTION_MOVE");
                break;
            case MotionEvent.ACTION_UP:
                Log.e("MyTextView","dispatchTouchEvent:ACTION_UP");
                break;
        }
        return super.dispatchTouchEvent(event);
    }
}
2).Activity代码(重写dispatchTouchEvent和onTouchEvent并为MyTextView设置触摸事件)
public class MainActivity extends AppCompatActivity implements View.OnClickListener,View.OnTouchListener{

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        MyTextView myTextView=findViewById(R.id.tv);
        myTextView.setOnClickListener(this);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                Log.e("MainActivity","onTouchEvent:ACTION_DOWN");
                break;
            case MotionEvent.ACTION_MOVE:
                Log.e("MainActivity","onTouchEvent:ACTION_MOVE");
                break;
            case MotionEvent.ACTION_UP:
                Log.e("MainActivity","onTouchEvent:ACTION_UP");
                break;
        }
        return super.onTouchEvent(event);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        switch (ev.getAction()){
            case MotionEvent.ACTION_DOWN:
                Log.e("MainActivity","dispatchTouchEvent:ACTION_DOWN");
                break;
            case MotionEvent.ACTION_MOVE:
                Log.e("MainActivity","dispatchTouchEvent:ACTION_MOVE");
                break;
            case MotionEvent.ACTION_UP:
                Log.e("MainActivity","dispatchTouchEvent:ACTION_UP");
                break;
        }
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public void onClick(View v) {
        Log.e("MyTextView","onClick");
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                Log.e("MainActivity","onTouch:ACTION_DOWN");
                break;
            case MotionEvent.ACTION_MOVE:
                Log.e("MainActivity","onTouch:ACTION_MOVE");
                break;
            case MotionEvent.ACTION_UP:
                Log.e("MainActivity","onTouch:ACTION_UP");
                break;
        }
        return false;
    }
}
3).设置不同返回值时的结果
◇保持默认值
07-23 13:55:25.707 16976-16976/com.itfitness.viewandviewgroup E/MainActivity: dispatchTouchEvent:ACTION_DOWN
07-23 13:55:25.717 16976-16976/com.itfitness.viewandviewgroup E/MyTextView: dispatchTouchEvent:ACTION_DOWN
onTouchEvent:ACTION_DOWN
07-23 13:55:25.797 16976-16976/com.itfitness.viewandviewgroup E/MainActivity: dispatchTouchEvent:ACTION_UP
07-23 13:55:25.797 16976-16976/com.itfitness.viewandviewgroup E/MyTextView: dispatchTouchEvent:ACTION_UP
onTouchEvent:ACTION_UP
07-23 13:55:25.807 16976-16976/com.itfitness.viewandviewgroup E/MyTextView: onClick
◇改变Activity的dispatchTouchEvent方法返回值
true:(事件没有分发下去)
07-23 13:56:53.557 17565-17565/com.itfitness.viewandviewgroup E/MainActivity: dispatchTouchEvent:ACTION_DOWN
07-23 13:56:53.657 17565-17565/com.itfitness.viewandviewgroup E/MainActivity: dispatchTouchEvent:ACTION_UP
false:(事件同样没有分发下去)
07-23 13:58:16.377 18010-18010/com.itfitness.viewandviewgroup E/MainActivity: dispatchTouchEvent:ACTION_DOWN
07-23 13:58:16.457 18010-18010/com.itfitness.viewandviewgroup E/MainActivity: dispatchTouchEvent:ACTION_UP
◇改变MyTextView的dispatchTouchEvent方法返回值
true:(事件在MyTextView的dispatchTouchEvent方法被阻断)
07-23 13:59:39.087 18470-18470/com.itfitness.viewandviewgroup E/MainActivity: dispatchTouchEvent:ACTION_DOWN
07-23 13:59:39.087 18470-18470/com.itfitness.viewandviewgroup E/MyTextView: dispatchTouchEvent:ACTION_DOWN
07-23 13:59:39.177 18470-18470/com.itfitness.viewandviewgroup E/MainActivity: dispatchTouchEvent:ACTION_UP
07-23 13:59:39.187 18470-18470/com.itfitness.viewandviewgroup E/MyTextView: dispatchTouchEvent:ACTION_UP
false:(ACTION_DOWN事件在MyTextView的dispatchTouchEvent方法被阻断,并且MainActivity中执行了onTouchEvent方法)
07-23 14:03:03.517 19115-19115/com.itfitness.viewandviewgroup E/MainActivity: dispatchTouchEvent:ACTION_DOWN
07-23 14:03:03.517 19115-19115/com.itfitness.viewandviewgroup E/MyTextView: dispatchTouchEvent:ACTION_DOWN
07-23 14:03:03.517 19115-19115/com.itfitness.viewandviewgroup E/MainActivity: onTouchEvent:ACTION_DOWN
07-23 14:03:03.597 19115-19115/com.itfitness.viewandviewgroup E/MainActivity: dispatchTouchEvent:ACTION_UP
onTouchEvent:ACTION_UP
◇改变MyTextView的onTouchEvent返回值
true:(ACTION_DOWN事件传递到MyTextView并没有执行onClick方法)
07-23 14:07:47.317 20046-20046/com.itfitness.viewandviewgroup E/MainActivity: dispatchTouchEvent:ACTION_DOWN
07-23 14:07:47.317 20046-20046/com.itfitness.viewandviewgroup E/MyTextView: dispatchTouchEvent:ACTION_DOWN
onTouchEvent:ACTION_DOWN
07-23 14:07:47.387 20046-20046/com.itfitness.viewandviewgroup E/MainActivity: dispatchTouchEvent:ACTION_UP
07-23 14:07:47.387 20046-20046/com.itfitness.viewandviewgroup E/MyTextView: dispatchTouchEvent:ACTION_UP
onTouchEvent:ACTION_UP
false:(MyTextView没有消费事件反给了MainActivity并且没有执行onClick方法)
07-23 14:11:44.027 20717-20717/com.itfitness.viewandviewgroup E/MainActivity: dispatchTouchEvent:ACTION_DOWN
onTouchEvent:ACTION_DOWN
07-23 14:11:44.067 20717-20717/com.itfitness.viewandviewgroup E/MainActivity: dispatchTouchEvent:ACTION_UP
onTouchEvent:ACTION_UP

三.Activity与View事件传递总结

img_8fbea24ddb15bc4db1799ddef6f6ad66.png
image

个人博客:https://myml666.github.io

目录
相关文章
|
1月前
|
前端开发 编译器 Android开发
构建高效Android应用:探究Kotlin协程的异步处理机制
【4月更文挑战第2天】在现代移动应用开发中,提供流畅且响应迅速的用户体验是至关重要的。随着Android平台的发展,Kotlin语言凭借其简洁性和功能性编程的特点成为了主流选择之一。特别地,Kotlin协程作为一种新型的轻量级线程管理机制,为开发者提供了强大的异步处理能力,从而显著提升了应用程序的性能和响应速度。本文将深入探讨Kotlin协程在Android中的应用,分析其原理、实现以及如何通过协程优化应用性能。
|
4月前
|
存储 Java Android开发
Android系统升级的机制概要
Android系统升级的机制概要
52 0
|
6天前
|
Android开发
Android 12修改usb tp触摸唤醒
Android 12修改usb tp触摸唤醒
13 0
|
7天前
|
Android开发
Android Loader机制
Android Loader机制
12 1
|
20天前
|
存储 Android开发
Android 解决USB TP驱动中触摸卡顿和防抖动问题
Android 解决USB TP驱动中触摸卡顿和防抖动问题
21 1
|
20天前
|
XML 存储 Android开发
Android系统 添加动态控制USB TP触摸方向、触摸唤醒
Android系统 添加动态控制USB TP触摸方向、触摸唤醒
33 0
|
21天前
|
Android开发
Android 支持TP触摸唤醒
Android 支持TP触摸唤醒
8 0
|
1月前
|
API 调度 Android开发
探索Android应用程序的后台运行机制
在移动应用开发中,了解和掌握Android应用程序的后台运行机制至关重要。本文将深入探讨Android平台上应用程序的后台运行原理及其影响因素,包括后台服务、广播接收器、JobScheduler等关键组件,以及如何有效管理后台任务以提升应用性能和用户体验。
22 3
|
5月前
|
Android开发 容器
[Android]View的事件分发机制(源码解析)
[Android]View的事件分发机制(源码解析)
37 0
|
5月前
|
消息中间件 缓存 安全
android开发,使用kotlin学习消息机制Handler
android开发,使用kotlin学习消息机制Handler
102 0