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

目录
相关文章
|
4月前
|
Android开发 容器
[Android]View的事件分发机制(源码解析)
[Android]View的事件分发机制(源码解析)
36 0
|
4月前
|
消息中间件 缓存 安全
android开发,使用kotlin学习消息机制Handler
android开发,使用kotlin学习消息机制Handler
81 0
|
4月前
|
安全 Android开发 Kotlin
android开发,使用kotlin学习Android权限机制
android开发,使用kotlin学习Android权限机制
40 0
|
4月前
|
XML Java Android开发
Android App接管手势处理TouchEvnet中单点触摸和多点触控的讲解及实战(附源码 超简单实用)
Android App接管手势处理TouchEvnet中单点触摸和多点触控的讲解及实战(附源码 超简单实用)
36 0
|
4月前
|
XML Java Android开发
Android App开发触摸事件中手势事件Event的分发流程讲解与实战(附源码 简单易懂)
Android App开发触摸事件中手势事件Event的分发流程讲解与实战(附源码 简单易懂)
43 0
|
8月前
|
Android开发
Android 使用Alarm机制创建长时间在后台运行的定时任务
Android 使用Alarm机制创建长时间在后台运行的定时任务
158 0
|
8月前
|
Java API Android开发
Android 权限机制详解
Android 权限机制详解
74 0
|
8月前
|
XML 消息中间件 API
Android 中handler消息机制的理解
Android 中handler消息机制的理解
48 0
|
调度 Android开发
Android异步消息处理机制之Handler、Looper、Message
因为Android UI线程是线程不安全的,在子线程中更新UI会直接程序崩溃,另外当UI线程需要执行一个比较耗时的操作的话(IO操作,网络通信等),若是执行时间超过5s,程序会直接ANR,为了解决上述问题,可以使用异步消息处理机制[Handler]
|
设计模式 前端开发 Java
Android体系课之--Kotlin协程进阶篇-协程的异常处理机制以及suspend关键字(三)
协程通过将复杂性放入库来简化异步编程。程序的逻辑可以在协程中顺序地表达,而底层库会为我们解决其异步性。该库可以将用户代码的相关部分包装为回调、订阅相关事件、在不同线程(甚至不同机器!)上调度执行,而代码则保持如同顺序执行一样简单。