Android触摸事件处理机制之requestDisallowInterceptTouchEvent

本文主要是介绍Android触摸事件处理机制之requestDisallowInterceptTouchEvent,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、触摸事件传递的规则

当手指触摸到屏幕时,系统就会调用相应的ViewonTouchEvent,并传入一系列的action。当有多个层级的View时,在父层级允许的情况下,这个action会一直向下传递直到遇到最深层的View。所以touch事件最先调用的是最底层ViewonTouchEvent,如果ViewonTouchEvent接收到某个touchaction并做了相应处理,最后有两种返回方式: retrun true returnfalsereturn true会告诉系统当前的View需要处理这次touch事件,以后系统发出的ACTION_MOVE,ACTION_UP等还是需要继续监听并接收的,而且这次的action已经被处理掉了,父层的View是不可能触发onTouchEvent了,所以每一个action最多只能有一个onTouchEvent接口返回true。如果返回false,便会通知系统,当前View不关心这一次的touch事件,此时这个action会传向父级,调用父级ViewonTouchEvent,但是这一次的touch事件之后发出的任何action,该View都不会再接受,onTouchEvent在这一次的touch事件中再也不会触发,也就是说一旦View返回false,那么之后的ACTION_MOVE,ACTION_UPaction就不会再传入这个view,但是下一次touch事件的action还是会传进来的。

   前面说到了底层的View能够接受到这次事件有一个前提:在父层级允许的情况下。假设不改变父层级的dispatch方法,在系统调用底层onTouchEvent之前会先调用父View的方法判断,父层View是不是要截获本次touch事件之后的action。如果onInterceptTouchEvent返回了true,那么本次touch事件之后的所有action都不会再向深层次的View传递,统统都会传给父层View的onTouchEvent,就是说父层已经截获了这次touch事件,之后的action也不必询问onInterceptTouchEvent,在这次的touch事件之后发出的action时,onInterceptTouchEvent不会再调用,直到下一次touch事件的来临。如果onInterceptTouchEvent返回false,那么本次action将发送给更深层的View,并且之后的每一次action都会询问父层的onInterceptTouchEvent需不需要截获本次touch事件。只有ViewGroup才有onInterceptTouchEvent方法,因为一个普通的View肯定是位于最深层的View,touch事件能够传到这里已经是最后一站了,肯定会调用View的onTouchEvent。

    对于底层的View来说,有一种方法可以阻止父层的View截获touch事件,就是调用getParent().requestDisallowInterceptTouchEvent(true);方法。一旦底层View收到touchaction后调用这个方法那么父层View就不会再调用onInterceptTouchEvent了,也无法截获以后的action。

 

 

 

 

二、事例分析

     用例子总结一下onInterceptTouchEvent  onTouchEvent的调用顺序。   假设最高层ViewOuterLayout     中间层ViewInnerLayout     最底层ViewMyView

    调用的顺序是这样的(假设各个函数返回的都是false)OuterLayout.onInterceptTouchEvent  -> InnerLayout.onInterceptTouchEvent-> MyView.onTouchEvent -> InnerLayout.onTouchEvent ->OuterLayout.onTouchEvent

public boolean dispatchTouchEvent(MotionEvent ev) {   getParent().requestDisallowInterceptTouchEvent(true);  return super.dispatchTouchEvent(ev);    
} 

 

    这句话是告诉父View,我的事件自己处理

public boolean onTouch(View v, MotionEvent event) {  switch (event.getAction()) {  case MotionEvent.ACTION_MOVE:   pager.requestDisallowInterceptTouchEvent(true);  break;  case MotionEvent.ACTION_UP:  case MotionEvent.ACTION_CANCEL:  pager.requestDisallowInterceptTouchEvent(false);  break;  }  
}


    也可以写成类似于上面那样,当用户按下的时候,我们告诉父组件,不要拦截我的事件(这个时候子组件是可以正常响应事件的),拿起之后就会告诉父组件可以阻止。

 

 

 

 

三、一个关于子控件和父控件的事件响应问题

    当父控件中有子控件的时候,并且父控件和子控件都有事件处理(比如单击事件)。这时,点击子控件,父控件的单击事件就无效了。

    比如:一个LinearLayout里面有一个子控件TextView,但是TextView的大小没有LinearLayout

     1.如果LinearLayout和TextView都设置了单击事件,那么:

  • 点击TextView区域的时候,触发的是TextView的事件。
  • 点击TextView以外的区域的时候,触发LinearLayout的事件。

     2.如果LinearLayout设置了单击事件,而TextView没有设置单机事件的话,那么

  • 不管单击的是TextView区域,还是TextView以外的区域,都是触发LinearLayout的单击事件

    如果两个控件一样大:

 1.如果LinearLayout和TextView都设置了单击事件,那么:

  • 只有TextView的单击事件有效

     2.如果LinearLayout设置了单击事件,而TextView没有设置单机事件的话,那么

  • 触发LinearLayout的单击事件

 

 

 

public boolean onInterceptTouchEvent (MotionEvent ev)

 

Implement this methodto intercept all touch screen motion events. This allows you to watch events asthey are dispatched to your children, and take ownership of the current gestureat any point.

Using this functiontakes some care, as it has a fairly complicated interaction withView.onTouchEvent(MotionEvent),and using it requires implementing that method as well as this one in thecorrect way. Events will be received in the following order:

  1. You will receive the down event here.
  2. The down event will be handled either by a child of this view group, or given to your own onTouchEvent() method to handle; this means you should implement onTouchEvent() to return true, so you will continue to see the rest of the gesture (instead of looking for a parent view to handle it). Also, by returning true from onTouchEvent(), you will not receive any following events in onInterceptTouchEvent() and all touch processing must happen in onTouchEvent() like normal.
  3. For as long as you return false from this function, each following event (up to and including the final up) will be delivered first here and then to the target's onTouchEvent().
  4. If you return true from here, you will not receive any following events: the target view will receive the same event but with the actionACTION_CANCEL, and all further events will be delivered to your onTouchEvent() method and no longer appear here.

Parameters

ev

The motion event being dispatched down the hierarchy.

Returns

  • Return true to steal motion events from the children and have them dispatched to this ViewGroup through onTouchEvent(). The current target will receive an ACTION_CANCEL event, and no further messages will be delivered here.

这篇关于Android触摸事件处理机制之requestDisallowInterceptTouchEvent的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1145448

相关文章

一文带你理解Python中import机制与importlib的妙用

《一文带你理解Python中import机制与importlib的妙用》在Python编程的世界里,import语句是开发者最常用的工具之一,它就像一把钥匙,打开了通往各种功能和库的大门,下面就跟随小... 目录一、python import机制概述1.1 import语句的基本用法1.2 模块缓存机制1.

Redis主从/哨兵机制原理分析

《Redis主从/哨兵机制原理分析》本文介绍了Redis的主从复制和哨兵机制,主从复制实现了数据的热备份和负载均衡,而哨兵机制可以监控Redis集群,实现自动故障转移,哨兵机制通过监控、下线、选举和故... 目录一、主从复制1.1 什么是主从复制1.2 主从复制的作用1.3 主从复制原理1.3.1 全量复制

Redis缓存问题与缓存更新机制详解

《Redis缓存问题与缓存更新机制详解》本文主要介绍了缓存问题及其解决方案,包括缓存穿透、缓存击穿、缓存雪崩等问题的成因以及相应的预防和解决方法,同时,还详细探讨了缓存更新机制,包括不同情况下的缓存更... 目录一、缓存问题1.1 缓存穿透1.1.1 问题来源1.1.2 解决方案1.2 缓存击穿1.2.1

Java如何通过反射机制获取数据类对象的属性及方法

《Java如何通过反射机制获取数据类对象的属性及方法》文章介绍了如何使用Java反射机制获取类对象的所有属性及其对应的get、set方法,以及如何通过反射机制实现类对象的实例化,感兴趣的朋友跟随小编一... 目录一、通过反射机制获取类对象的所有属性以及相应的get、set方法1.遍历类对象的所有属性2.获取

MySQL中的锁和MVCC机制解读

《MySQL中的锁和MVCC机制解读》MySQL事务、锁和MVCC机制是确保数据库操作原子性、一致性和隔离性的关键,事务必须遵循ACID原则,锁的类型包括表级锁、行级锁和意向锁,MVCC通过非锁定读和... 目录mysql的锁和MVCC机制事务的概念与ACID特性锁的类型及其工作机制锁的粒度与性能影响多版本

JavaScript DOM操作与事件处理方法

《JavaScriptDOM操作与事件处理方法》本文通过一系列代码片段,详细介绍了如何使用JavaScript进行DOM操作、事件处理、属性操作、内容操作、尺寸和位置获取,以及实现简单的动画效果,涵... 目录前言1. 类名操作代码片段代码解析2. 属性操作代码片段代码解析3. 内容操作代码片段代码解析4.

Android数据库Room的实际使用过程总结

《Android数据库Room的实际使用过程总结》这篇文章主要给大家介绍了关于Android数据库Room的实际使用过程,详细介绍了如何创建实体类、数据访问对象(DAO)和数据库抽象类,需要的朋友可以... 目录前言一、Room的基本使用1.项目配置2.创建实体类(Entity)3.创建数据访问对象(DAO

Spring使用@Retryable实现自动重试机制

《Spring使用@Retryable实现自动重试机制》在微服务架构中,服务之间的调用可能会因为一些暂时性的错误而失败,例如网络波动、数据库连接超时或第三方服务不可用等,在本文中,我们将介绍如何在Sp... 目录引言1. 什么是 @Retryable?2. 如何在 Spring 中使用 @Retryable

Android WebView的加载超时处理方案

《AndroidWebView的加载超时处理方案》在Android开发中,WebView是一个常用的组件,用于在应用中嵌入网页,然而,当网络状况不佳或页面加载过慢时,用户可能会遇到加载超时的问题,本... 目录引言一、WebView加载超时的原因二、加载超时处理方案1. 使用Handler和Timer进行超

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization