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

目录
相关文章
|
3天前
|
存储 安全 Android开发
探索Android与iOS的隐私保护机制
在数字化时代,移动设备已成为我们生活的一部分,而隐私安全是用户最为关注的问题之一。本文将深入探讨Android和iOS两大主流操作系统在隐私保护方面的策略和实现方式,分析它们各自的优势和不足,以及如何更好地保护用户的隐私。
|
1月前
|
消息中间件 存储 Java
Android消息处理机制(Handler+Looper+Message+MessageQueue)
Android消息处理机制(Handler+Looper+Message+MessageQueue)
38 2
|
22天前
|
消息中间件 存储 Java
Android面试高频知识点(2) 详解Android消息处理机制(Handler)
Android面试高频知识点(2) 详解Android消息处理机制(Handler)
|
26天前
|
消息中间件 存储 Java
Android面试高频知识点(2) 详解Android消息处理机制(Handler)
Android面试高频知识点(2) 详解Android消息处理机制(Handler)
46 1
|
27天前
|
存储 安全 数据安全/隐私保护
探索安卓与iOS的隐私保护机制####
【10月更文挑战第15天】 本文深入剖析了安卓和iOS两大操作系统在隐私保护方面的策略与技术实现,旨在揭示两者如何通过不同的技术手段来保障用户数据的安全与隐私。文章将逐一探讨各自的隐私控制功能、加密措施以及用户权限管理,为读者提供一个全面而深入的理解。 ####
46 1
|
29天前
|
消息中间件 存储 Java
Android消息处理机制(Handler+Looper+Message+MessageQueue)
Android消息处理机制(Handler+Looper+Message+MessageQueue)
44 2
|
2月前
|
存储 缓存 Android开发
Android RecyclerView 缓存机制深度解析与面试题
本文首发于公众号“AntDream”,详细解析了 `RecyclerView` 的缓存机制,包括多级缓存的原理与流程,并提供了常见面试题及答案。通过本文,你将深入了解 `RecyclerView` 的高性能秘诀,提升列表和网格的开发技能。
66 8
|
3月前
|
消息中间件 存储 Java
Android面试高频知识点(2) 详解Android消息处理机制(Handler)
Android 消息处理机制估计都被写烂了,但是依然还是要写一下,因为Android应用程序是通过消息来驱动的,Android某种意义上也可以说成是一个以消息驱动的系统,UI、事件、生命周期都和消息处理机制息息相关,并且消息处理机制在整个Android知识体系中也是尤其重要,在太多的源码分析的文章讲得比较繁琐,很多人对整个消息处理机制依然是懵懵懂懂,这篇文章通过一些问答的模式结合Android主线程(UI线程)的工作原理来讲解,源码注释很全,还有结合流程图,如果你对Android 消息处理机制还不是很理解,我相信只要你静下心来耐心的看,肯定会有不少的收获的。
198 3
Android面试高频知识点(2) 详解Android消息处理机制(Handler)
|
5月前
|
安全 算法 数据安全/隐私保护
探索iOS与Android的隐私保护机制
【6月更文挑战第5天】在数字时代,隐私保护已成为用户最关心的问题之一。iOS和Android作为两大主流操作系统,各自发展出了独特的隐私保护技术。本文将深入探讨这两个平台在隐私保护方面的策略、技术和挑战。
142 3
|
5月前
|
Android开发 虚拟化 异构计算
一文搞定Android VSync机制来龙去脉
一文搞定Android VSync机制来龙去脉
230 0