Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >事件分发机制三问

事件分发机制三问

作者头像
码上积木
发布于 2020-10-10 01:55:21
发布于 2020-10-10 01:55:21
47500
代码可运行
举报
文章被收录于专栏:码上积木码上积木
运行总次数:0
代码可运行

只要有点击,就会涉及到事件分发机制,点击屏幕后,view会怎么反应?今天一起来看看事件分发机制的三问:

  • Activity、View、Window 之间的关系。
  • 说说Android的事件分发机制完整流程,也就是从点击屏幕开始,事件会怎么传递。
  • 解决滑动冲突的办法。

Activity、View、Window 之间的关系。

每个 Activity 包含了一个 Window对象,这个对象是由 PhoneWindow做的实现。而 PhoneWindowDecorView作为了一个应用窗口的根 View,这个 DecorView 又把屏幕划分为了两个区域:一个是 TitleView,一个是ContentView,而我们平时在 Xml 文件中写的布局正好是展示在 ContentView 中的。

说说Android的事件分发机制完整流程,也就是从点击屏幕开始,事件会怎么传递。

我觉得事件分发机制流程可以分为三部分,分别是从外传里,从里传外,消费之后

1)「首先,从最外面一层传到最里面一层:」

如果当前是viewgroup层级,就会判断 onInterceptTouchEvent是否为true,如果为true,则代表事件要消费在这一层级,不再往下传递。接着便执行当前 viewgroup 的onTouchEvent方法。如果onInterceptTouchEvent为false,则代表事件继续传递到下一层级的 dispatchTouchEvent方法,接着一样的代码逻辑,一直到最里面一层的view。

伪代码解释:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public boolean dispatchTouchEvent(MotionEvent event) {
    boolean isConsume = false;
    if (isViewGroup) {
        if (onInterceptTouchEvent(event)) {
            isConsume = onTouchEvent(event);
        } else {
            isConsume = child.dispatchTouchEvent(event);
        }

    } else {
        //isView
        isConsume = onTouchEvent(event);
    }
    return isConsume;
}

2)「到最里层的view之后,view本身还是可以选择消费或者传到外面。」

到最里面一层就会直接执行onTouchEvent方法,这时候,view有没有权利拒绝消费事件呢?按道理view作为最底层的,应该是没有发言权才对。但是呢,秉着公平公正原则,view也是可以拒绝的,可以在onTouchEvent方法返回false,表示他不想消费这个事件。那么它的父容器onTouchEvent又会被调用,如果父容器的onTouchEvent又返回false,则又交给上一级。一直到最上层,也就是Activity的onTouchEvent被调用。

伪代码解释:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public void handleTouchEvent(MotionEvent event) {
    if (!onTouchEvent(event)) {
        getParent.onTouchEvent(event);
    }
}

3)「消费之后」

当某一层viewGroup的onInterceptTouchEvent为true,则代表当前层级要消费事件。如果它的onTouchListener被设置了的话,则onTouch会被调用,如果onTouch的返回值返回true,则onTouchEvent不会被调用。如果返回false或者没有设置onTouchListener,则会继续调用onTouchEvent。而onClick方法则是设置了onClickListener则会被正常调用。

伪代码解释:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public void consumeEvent(MotionEvent event) {
    if (setOnTouchListener) {
        int tag = onTouch();
        if (!tag) {
            onTouchEvent(event);
        }
    } else {
        onTouchEvent(event);
    }

    if (setOnClickListener) {
        onClick();
    }
}

解决滑动冲突的办法。

解决滑动冲突的根本就是要在适当的位置进行拦截,那么就有两种解决办法:

  • 外部拦截:从父view端处理,根据情况决定事件是否分发到子view
  • 内部拦截:从子view端处理,根据情况决定是否阻止父view进行拦截,其中的关键就是requestDisallowInterceptTouchEvent方法。

1)「外部拦截法」,其实就是在onInterceptTouchEvnet方法里面进行判断,是否拦截,见代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    //外部拦截法:父view.java  
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        boolean intercepted = false;
        //父view拦截条件
        boolean parentCanIntercept;

        switch (ev.getActionMasked()) {
            case MotionEvent.ACTION_DOWN:
                intercepted = false;
                break;
            case MotionEvent.ACTION_MOVE:
                if (parentCanIntercept) {
                    intercepted = true;
                } else {
                    intercepted = false;
                }
                break;
            case MotionEvent.ACTION_UP:
                intercepted = false;
                break;
        }
        return intercepted;

    }

还是比较简单的,直接判断拦截条件,然后返回true就代表拦截,false就不拦截,传到子view。注意的是ACTION_DOWN状态不要拦截,如果拦截,那么后续事件就直接交给父view处理了,也就没有拦截不拦截的问题了。

  1. 「内部拦截法」,就是通过requestDisallowInterceptTouchEvent方法让父view不要拦截。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    //父view.java   
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
            return false;
        } else {
            return true;
        }
    }

    //子view.java
    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        //父view拦截条件
        boolean parentCanIntercept;

        switch (event.getActionMasked()) {
            case MotionEvent.ACTION_DOWN:
                getParent().requestDisallowInterceptTouchEvent(true);
                break;
            case MotionEvent.ACTION_MOVE:
                if (parentCanIntercept) {
                    getParent().requestDisallowInterceptTouchEvent(false);
                }
                break;
            case MotionEvent.ACTION_UP:
                break;
        }
        return super.dispatchTouchEvent(event);
    }

requestDisallowInterceptTouchEvent(true)的意思是阻止父view拦截事件,也就是传入true之后,父view就不会再调用onInterceptTouchEvent。反之,传入false就代表父view可以拦截,也就是会走到父view的onInterceptTouchEvent方法。所以需要父view拦截的时候,就传入flase,需要父view不拦截的时候就传入true。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-10-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码上积木 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
拇指记者打探事件分发机制背后的秘密(下)
上一期跟随拇指记者,发现了Android公司在指派具体的人之前的种种机制,今天就继续探索,看看任务具体的处理消费逻辑。
码上积木
2021/04/16
4560
这次,我把Android事件分发机制翻了个遍
作者:积木zz 链接:https://juejin.im/post/5eb3e0d6f265da7c002028cd 以下是原文:
胡飞洋
2020/07/23
2.2K0
这次,我把Android事件分发机制翻了个遍
笔记——事件分发机制(四)
1、事件分发机制:整个事件分发是一个U形传递的,递归传递。图解 Android 事件分发机制
木溪bo
2018/12/27
8611
Android面试老生常谈的 View 事件分发机制,看这一篇就够了!
在 Android 开发当中,View 的事件分发机制是一块很重要的知识。不仅在开发当中经常需要用到,面试的时候也经常被问到。
程序员徐公
2021/06/01
7110
Android面试老生常谈的 View 事件分发机制,看这一篇就够了!
笔记(四)——事件分发机制
1、事件分发机制:整个事件分发是一个U形传递的,递归传递。图解 Android 事件分发机制
木溪bo
2020/03/27
1.4K0
验证和分析Android的事件分发机制
由于篇幅原因,实例验证过程记录到这里:Android事件分发机制验证示例 ,可以点击阅读原文查看。 大家主要关注里面打印的日志信息,看下事件分发的过程即可。
103style
2022/12/19
3430
验证和分析Android的事件分发机制
android viewgroup事件分发机制
今天给大家代码ViewGroup事件分发的源码解析~~凡是自定义ViewGroup实现各种滑动效果的,不可避免的会出现很多事件的冲突,对ViewGroup事件分发机制的了解,也有益于大家了解冲突产生的原因,以及对冲突进行处理~ 1、案例 首先我们接着上一篇的代码,在代码中添加一个自定义的LinearLayout: package com.example.zhy_event03;   import android.content.Context;   import android.util.Attrib
xiangzhihong
2018/01/30
1K0
进阶必备-Android事件分发机制
或许你会问,“为什么我一定要知道View的事件分发机制?”。因为我们在实际开发的过程中,经常会遇到多层的View互相嵌套以后,对某一个View进行滑动的时候,特别不灵敏,甚至于没法滑动。这种滑动冲突的解决需要我们清楚的掌握View的事件分发机制。那下面我们详细的讲解下View的整个事件机制。 Android将View的事件封装到MotionEvent这个类中,这也是监听touch事件中回调给我们的参数public boolean onTouchEvent(MotionEvent event) 。通常事件我们主要关心下面几种类型:
吴延宝
2018/10/18
9700
进阶必备-Android事件分发机制
View的事件分发及滑动冲突的解决
一次触摸事件,ACTION_DOWN和ACTION_UP是必须存在的,ACTION_MOVE视情况而定。
程序员小何SS
2021/11/30
9270
重新复习Android View事件分发
一个Activity包含了一个Window对象,这个对象是由PhoneWindow来实现的。PhoneWindow将DecorView作为整个应用窗口的根View,而这个DecorView又将屏幕划分为两个区域:一个是TitleView,另一个是ContentView,而我们平时所写的就是展示在ContentView中
老马的编程之旅
2022/06/22
3910
重新复习Android View事件分发
View的事件分发机制
当一个点击事件产生后,他的传递过程遵循Activity->Window->View的逐级传递。我们这里讨论的是在Android系统View里事件传递。
1025645
2018/08/23
4280
一文读懂Android View事件分发机制
Android View 虽然不是四大组件,但其并不比四大组件的地位低。而View的核心知识点事件分发机制则是不少刚入门同学的拦路虎。ScrollView嵌套RecyclerView(或者ListView)的滑动冲突这种老大难的问题的理论基础就是事件分发机制。
陈宇明
2020/12/15
3870
一文读懂Android View事件分发机制
Android必知必会--事件分发机制
所谓的安卓事件是什么?具体来说的就是点击和滑动两个操作;抽象着来说就是下面的表格。
ClericYi
2020/07/21
6220
View事件分发机制源码解析
注:本文解析的源码基于 API 25,部分内容来自于《Android开发艺术探索》。
俞其荣
2022/07/28
4100
Android技能树 — View事件体系小结
这次是讲View的事件体系。特别是不同情况下的事件分发,我会用很简单的方式教会大家。
青蛙要fly
2018/08/29
3880
Android技能树 — View事件体系小结
开发笔记-自定义View(十)-View的事件分发机制
关于自定义View系列的文章,好久没有写了。今天抽空看了下Android开发艺术探索。正好看到了View的事件分发机制,所以将它写成笔记记录下来。 关于View的事件分发,我起初是学习郭神的2篇文章。感觉其实也没有什么。大致也就了解下。不过看完其他很多优秀的文章和书籍后,才知道自己too young too simple。下面我们就一起来分析下Android的时间分发机制。
g小志
2018/09/11
6680
开发笔记-自定义View(十)-View的事件分发机制
Android事件分发机制完全解析,带你从源码的角度彻底理解(下)
记得在前面的文章中,我带大家一起从源码的角度分析了Android中View的事件分发机制,相信阅读过的朋友对View的事件分发已经有比较深刻的理解了。 还未阅读过的朋友,请先参考 Android事件分
用户1158055
2018/01/05
1.3K0
Android事件分发机制完全解析,带你从源码的角度彻底理解(下)
高级 UI 成长之路 (二) 深入理解 Android 8.0 View 触摸事件分发机制
在上一篇文章中我们介绍了 View 的基础知识以及 View 滑动的实现,本篇将为大家带来 View 的一个核心知识点 事件分发机制。事件分发机制不仅仅是核心知识点也是 Android 中的一个难点,下面我们就从源码的角度来分析事件的传递还有最后是如何解决滑动冲突的。
做个快乐的码农
2021/11/12
7590
高级 UI 成长之路 (二) 深入理解 Android 8.0 View 触摸事件分发机制
Android面试官必问的事件分发,你答得上来吗?
image.png Android touch 事件的分发,是面试中最常被问到的问题之一。我们来看看 😎、😨 和 🤔️ 三位同学是怎么回答的吧 😎 自认为无所不知,水平已达应用开发天花板,目前月薪 10k 面试官:讲讲 Android 的事件分发机制 😎:当用户手指触摸屏幕时,Android 会将对应的事件包装成一个事件对象 MotionEvent ,从 ViewTree 的顶部至上而下地分发传递。用户从手指接触屏幕至离开屏幕会产生一系列的事件,事件是以 down 开始,up 或 cancel 结束,中间
Android技术干货分享
2020/05/18
1.1K0
Android面试官必问的事件分发,你答得上来吗?
带你一起探究Android事件分发机制, 让面试提问不在畏惧!
大家知道Android中的视图是由一个个View嵌套构成的层级视图,即一个View里包含有子View,而这个子View里面又可以再添加View。当用户触摸屏幕产生一系列事件时,事件会由高到低,由外向内依次传递,最终把事件交到一个具体的View手上处理,这个传递的过程就叫做事件分发。
Android技术干货分享
2019/07/09
1.4K0
相关推荐
拇指记者打探事件分发机制背后的秘密(下)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验