View事件冲突——事件分发机制

当设备接受到屏幕事件(即MotionEvent中定义的一些ACTION),经操作系统处理后,会逐层向上传递,直到事件被接收处理。

MotionEventAction

01. 问题描述

在嵌套布局中,常常会有子View与父View(指嵌套子View的容器View,非继承关系)具有同样的操作逻辑,例如

listViewInViewPager

可横向滑动的ViewPager实例中嵌套了一个可横向滑动的ListView实例,在横向滑动ListView时,极易发生ViewPager先处理了横向滑动事件,导致事件无法继续向上传递给ListView。

02. 产生原因

2.1 View事件分发机制

viewDispatchEvent

  • View类似于swing中的JPanel,代表一个空白的矩形区域,Android应用中的绝大部分UI组件都继承于View或其子类
  • View还一个重要的子类ViewGroup,它通常作为其它组件的[容器]
  • 简单来讲View是所有控件的父控件,ViewGroup可以包含其它的View对象,并且是所有布局控件的父类
  • Activity相当于一个展板,本身没有可视的内容,你把画(View)贴到展板上就可以展示出来setContentView(view)

2.2

  • dispatchTouchEvent:分发事件的
  • onInterceptTouchEvent:拦截事件的
  • 注:ViewGroup才有这个方法,View没有onInterceptTouchEvent这个方法
  • onTouchEvent:来处理事件的
  • requestDisallowInterceptTouchEvent(true)
    • 影响父View是否拦截事件
    • true表示不拦截事件,false表示拦截事件

03. 解决办法

  • 从ParentView着手解决
    • 重写onInterceptTouchEvent()方法,返回false【不拦截事件】
  • 从ChildView着手解决
    • 重写dispatchTouchEvent(MotionEvent ev)
      • 在MotionEvent.ACTION_DOWN时就返回true【拦截事件】
    • 重写onInterceptTouchEvent(MotionEvent ev)亦有同样效果
dark
sans