当设备接受到屏幕事件(即MotionEvent中定义的一些ACTION),经操作系统处理后,会逐层向上传递,直到事件被接收处理。
01. 问题描述
在嵌套布局中,常常会有子View与父View(指嵌套子View的容器View,非继承关系)具有同样的操作逻辑,例如
可横向滑动的ViewPager实例中嵌套了一个可横向滑动的ListView实例,在横向滑动ListView时,极易发生ViewPager先处理了横向滑动事件,导致事件无法继续向上传递给ListView。
02. 产生原因
2.1 View事件分发机制
- 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)亦有同样效果
- 重写dispatchTouchEvent(MotionEvent ev)