热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

AndroidView分发机制

一、介绍  什么是分发机制?    首先了解下什么是分发机制,分发机制顾名思义,用来实现分配的功能,好比一个公司领导下发任务给部门领
一、介绍

    什么是分发机制?

    首先了解下什么是分发机制,分发机制顾名思义,用来实现分配的功能,好比一个公司领导下发任务给部门领导,部门领导下发任务给员工。

    View分发机制的作用

    分发机制在view中起到什么作用呢,和上面举例类似,它的作用是用来分发view的点击事件,我们常遇到的如滑动冲突问题,就是典型的分发机制的一个难点,分发机制说起来难其实也不难,说简单也不简单,下面会一一介绍.

二、分发机制的传递规则    

    首先了解规则之前我们先了解几个关键对象

    1.MotionEvent

      这个应该都不陌生,点击事件的对象,从这个对象中可以获取到我的点击事件当前的状态,像MotionEvent.ACTION_UP、MotionEvent.ACTION_DOWN、MotionEvent.ACTION_MOVE,在事件分发中也是必不可少的一个对象.

    2. 事件分发几个关键方法

        ①dispatchTouchEvent()–>分工

                此方法作用在于分发任务,一个view执行分发之前首先会执行此方法,用来分发任务,我们可以理解为领导管理者,领导向下分发任务,起到一个管理分工作用.                

        ②onInterceptTouchEvent()–>拦截

                此方法作用在于拦截事件,当领导层也就是dispatchTouchEvent方法下发了分发任务,如果需要执行此任务就需要此方法告知我们的领导层(dispatchTouchEvent),我要接受这个任务,起到一个拦截任务的作用,如果不拦截则会由其他下级view处理是否拦截.

        ③onTouchEvent()–>处理

                  此方法作用在于处理事件,当我们拦截了分发的事件任务的时候,我们需要用到此方法来处理这次分发的任务,如果此方法不处理,则分发给下一级view去处理,例如我们接受了领导下发的任务,也成功拦截接受了任务,在处理的时候我们发现我们处理不了次任务或者不想处理,这时候就需要给其他员工去处理 (子view).

    3.分发规则

        想了解分发的传递规则首先我们一起看下这段伪代码,能更好理解.

        public boolean dispatchTouchEvent(MotionEvent ev){

            boolean cOnsume= false;

            if(onInterceptTouchEvent(ev)){

                    cOnsume= onTouchEvent(ev);

            }else{

                    cOnsume= child.dispatchTouchEvent(ev);

            }

            return consume;

        }

        由上代码可以很清楚的看出,分发的传递规则,首先dispatchTouchEvent归属于顶层view,默认consume返回false也就是不处理此次事件,但是我们看到onInterceptTouchEvent方法如果返回true,也就是说我们拦截了事件,这个时候会走此view的onTouchEvent方法,当onTouchEvent方法返回true的时候代表此次事件我们这个顶层view处理了,其他view无需处理此事件,如果onTouchEvent返回false代表我们处理不了或者不处理此次事件,则dispatchTouchEvent直接返回false,如果我们不拦截此次事件的话也就是onInterceptTouchEvent返回false,我们可以看到else中有这样的代码 child.dispatchTouchEvent(ev);,child顾名思义代表子view,也就是说我们onInterceptTouchEvent返回false(不拦截此次事件的话),我们交由下一个子view进行处理,子view也按照这样的逻辑依次传递下去.

        分发顺序

             一般分发顺序由Activity->Window->View(开始分发)->子view

             上提到了分发规则,但是如果所有的view都不处理此次事件,那会如何呢?

              如果所有view都不处理的话,事件会传递给Activity处理.

        点击事件优先级

                点击事件一般会走如下方法:

                 OnTouch(也就是OnTouchListener)  > OnTouchEvent  >  OnClick.

                  由上可以看出点击事件的优先级, 当view处理点击事件时,首先会判断是否设置了OnTouchListener如果设置了那么OnTouch方法将被调用, 这时是否交由OnTouch方法还需要确认它的返回值, 如果返回false,则OnTouchEvent方法将被执行, 如果是true, OnTouchEvent不会被调用, 如果OnTouchEvent中,设置了OnClick则OnClick会被调用,也就是OnClick处理的优先级最低.

        3.滑动冲突

                  提到分发机制必不可少的就是滑动冲突这类问题,也是分发机制涉及的主要普遍疑难问题之一.

                  要解决这类问题我们首先了解下事件序列, 从手势按下也就是DOWN,到MOVE,最后手势抬起UP,这期间也就是分发事件过程,称之为一个事件序列.

                  那我们解决滑动冲突也就是说在这个事件序列中解决事件分发问题,也就是一个事件中特定的情况下(比如我向上滑动) 将这个向上滑动的操作,分发给哪个View去处理,这也是解决滑动冲突的原理.                    

                   第一种也就是2个同方向View的滑动冲突, 这类问题比较复杂, 想要解决需要配合实际的业务场景, 因为是同方向我们无法通过角度,滑动方向等来判断,需要分发给哪个view执行,这次事件序列, 因此我们就需要一些附加条件来作为我们判断的条件,比如当内部view在什么状态的情况下我分发给它此次事件序列,当外部view在另一个状态下分发给外部此次事件序列.

Android-View分发机制
同方向冲突

                    第二种也就是横竖两个方向View的滑动冲突, 这类问题算是相对比较好解决,一般viewpager会自动处理这类问题,如果外部使用viewpager的小伙伴不需要考虑冲突的问题,如果其他情况,则就需要用到分发机制来处理.

                     ① 外部拦截: 我们可以在外部view拦截,也就是使用拦截方法onInterceptTouchEvent,在此方法中判断我们的条件,可以根据滑动距离判断滑动方向以及角度,由此判断我们拦截方法是否返回true, 如果符合条件返回true,代表我们拦截了此方法,此时外部滑动生效, 如果返回false, 则不符合条件,交由内部view也就是子view处理。

                   ② 内部拦截: 内部拦截也就是外部不处理任何事件,在内部进行同样的条件判断是否拦截,如果内部拦截成功,则内部滑动生效,如果拦截失败也就是返回false,则交由上级view处理, 这里是反向分发可以理解为 ,不符合我们的分发机制,交由上层view处理的话这里需要用到parent.requestDisalLowInterCeptTouchEvent(false), 此方法作用也就是子view调用如下方法时,父view会继续拦截本次事件序列.

Android-View分发机制
横竖方向冲突  

            滑动冲突举例就这两种了目前,其他情况下可更加更复杂的情况判断分发事件.

 本文就到这里,如有错误请指正.


推荐阅读
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文介绍了在MFC下利用C++和MFC的特性动态创建窗口的方法,包括继承现有的MFC类并加以改造、插入工具栏和状态栏对象的声明等。同时还提到了窗口销毁的处理方法。本文详细介绍了实现方法并给出了相关注意事项。 ... [详细]
  • 本文详细介绍了Android中的坐标系以及与View相关的方法。首先介绍了Android坐标系和视图坐标系的概念,并通过图示进行了解释。接着提到了View的大小可以超过手机屏幕,并且只有在手机屏幕内才能看到。最后,作者表示将在后续文章中继续探讨与View相关的内容。 ... [详细]
  • 本文介绍了利用ARMA模型对平稳非白噪声序列进行建模的步骤及代码实现。首先对观察值序列进行样本自相关系数和样本偏自相关系数的计算,然后根据这些系数的性质选择适当的ARMA模型进行拟合,并估计模型中的位置参数。接着进行模型的有效性检验,如果不通过则重新选择模型再拟合,如果通过则进行模型优化。最后利用拟合模型预测序列的未来走势。文章还介绍了绘制时序图、平稳性检验、白噪声检验、确定ARMA阶数和预测未来走势的代码实现。 ... [详细]
  • android 触屏处理流程,android触摸事件处理流程 ? FOOKWOOD「建议收藏」
    android触屏处理流程,android触摸事件处理流程?FOOKWOOD「建议收藏」最近在工作中,经常需要处理触摸事件,但是有时候会出现一些奇怪的bug,比如有时候会检测不到A ... [详细]
  •  项目地址https:github.comffmydreamWiCar界面做的很难看,美工方面实在不在行。重点是按钮触摸事件的处理,这里搬了RepeatListener项目代码,例 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • Oracle分析函数first_value()和last_value()的用法及原理
    本文介绍了Oracle分析函数first_value()和last_value()的用法和原理,以及在查询销售记录日期和部门中的应用。通过示例和解释,详细说明了first_value()和last_value()的功能和不同之处。同时,对于last_value()的结果出现不一样的情况进行了解释,并提供了理解last_value()默认统计范围的方法。该文对于使用Oracle分析函数的开发人员和数据库管理员具有参考价值。 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • Android自定义控件绘图篇之Paint函数大汇总
    本文介绍了Android自定义控件绘图篇中的Paint函数大汇总,包括重置画笔、设置颜色、设置透明度、设置样式、设置宽度、设置抗锯齿等功能。通过学习这些函数,可以更好地掌握Paint的用法。 ... [详细]
  • 上图是InnoDB存储引擎的结构。1、缓冲池InnoDB存储引擎是基于磁盘存储的,并将其中的记录按照页的方式进行管理。因此可以看作是基于磁盘的数据库系统。在数据库系统中,由于CPU速度 ... [详细]
  • 单页面应用 VS 多页面应用的区别和适用场景
    本文主要介绍了单页面应用(SPA)和多页面应用(MPA)的区别和适用场景。单页面应用只有一个主页面,所有内容都包含在主页面中,页面切换快但需要做相关的调优;多页面应用有多个独立的页面,每个页面都要加载相关资源,页面切换慢但适用于对SEO要求较高的应用。文章还提到了两者在资源加载、过渡动画、路由模式和数据传递方面的差异。 ... [详细]
  • macOS命令行创建Android模拟器
    macOS下不安装AndroidStudio使用VSCode来开发Flutter应用使用命令行创建和管理Android模拟器设备avdmanageravdmanager 是一种命令 ... [详细]
  • 本文由编程笔记#小编为大家整理,主要介绍了css回到顶部按钮相关的知识,希望对你有一定的参考价值。 ... [详细]
author-avatar
手机用户2602936393
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有