Android-触摸时间与手势
单点触摸OnTouchListener
1.手指触碰屏幕时,触发MotionEvent事件。
2.该事件被OnTouchListener监听,可在它的onTouch()方法中获得该MotionEvent对象。
![](https://img.haomeiwen.com/i5014890/27acdceafd5aa067.png)
![](https://img.haomeiwen.com/i5014890/32bc36c18d77fd23.png)
总结:OnTouchListener一般用于单点的触摸监听需求,虽然也可以用它基本的多点触控功能,但是复杂的双击,长按等实现起来比较麻烦,而且Api也提供了供多点触摸需求直接使用GestureDetector.OnGestureListener接口。它能满足大部分下的多点触控需求。
多点触摸(手势)OnGestureListener
3.通过GestureDetector转发MotionEvent对象给OnGestureListener。
4.我们可以通过OnGestureListener获得该对象,然后获取相关信息,以及做相关处理。
![](https://img.haomeiwen.com/i5014890/556000527da313e9.png)
![](https://img.haomeiwen.com/i5014890/8c23a32a77b98098.png)
对于自定义View,使用手势识别有两处陷阱可能会浪费你的不少时间。(源于其他大神)
1:View必须设置longClickable为true,否则手势识别无法正确工作,只会返回Down, Show, Long三种手势
2:必须在View的onTouchListener中调用手势识别,而不能像Activity一样重载onTouchEvent,否则同样手势识别无法正确工作
View可以绑定的时间监听方法:
setOnClickListener - 当view被点击的时候回调
setOnDragListener -当view被拖动时回调
setOnFocusChangeListener - 当view改变焦点的时候回调
setOnGenericMotionListener- 任意的手势时回调
setOnHoverListener -在视图上悬停的时候调用
setOnKeyListener - 当view有焦点时候按硬件键时候回调
setOnLongClickListener - 长时间按压时回调
setOnTouchListener- 触摸view回调
其他特殊的View拥有自己的监听方法:如EditText,recycleView等
事件分发
事件传递的顺序:Activity -> ViewGroup -> View
事件处理函数
![](https://img.haomeiwen.com/i5014890/5bb450a81a9786c1.png)
![](https://img.haomeiwen.com/i5014890/604fd8c7604368b3.png)
事件分发流程
![](https://img.haomeiwen.com/i5014890/d23c265470c4bbac.png)
流程
①从activity的dispatchTouchEvent方法开始,
dispatchTouchEvent()若返回false调用onTouchEvent。
dispatchTouchEvent()若返回true,则表示事件不在分发,super,表示不拦截事件的分发,继续向下分发,事件分发传递给viewGourp。
②传递到ViewGourp后,从ViewGourp的dispatchEvent开始。
dispatchTouchEvent()若返回true,则表示事件不在分发,supter,表示不拦截事件的分发,继续向下分发。
dispatchTouchEvent()supter时调用ViewGourp的onInterceptTouchEvent方法决定是否要拦截次事件。
onInterceptTouchEven()若返回true,调用ViewGourp的onTouchEvent,表示事件被我拦截了。若返回false、supter,表示不拦截事件的分发,继续分发给下层view的dispatchEvent的事件。
③当底层view的dispatchEvent收到分发事件。
dispatchTouchEvent()若返回true,则表示事件不在分发。super,表示不拦截事件的分发,继续向下分发,事件分发结束,调用本层view的onTouchEvent。
返回false,不再调用本view的onTouchEvent,而是回调父ViewGourp的onTouchEvent。
④onTouchEvent只能且只会向上传递。
返回true,表示本view消费处理了此次点击事件,上层不会再收到onTouch时间。返回false,表示本view不消费处理,交给上层viewGourp处理,回调给上层viewGourp的onTouch
总结:
dispatchTouchEvent():事件分发
若返回true,则表示事件不在分发,后续的onInterceptTouchEven()或者 onTouchEvent()均不会被调用。
若返回false,则表示事件不会向下分发,会交于上层onTouchEvent()方法处理。
若返回super,则表示事件会分发。
onInterceptTouchEven():事件拦截
仅存在于ViewGourp的方法,表示事件是否拦截。
若返回true,则事件拦截,事件会交于本层onTouchEvent()方法处理。
若返回supe、falser,则表示事件不拦截,事件会继续向下层分发。
onTouchEvent();事件处理(消费)
仅会本层处理或向上传递。
若返回true,本层onTouchEvent()方法处理了。
若返回false,本层onTouchEvent()方法不处理,会调用上层的onTouchEvent()方法处理。
PS:事件的分发大体可以看成一个U型结构,只是可能会在中间的某一个环节断掉。
了解原理过后我们处理需求和冲突就手到擒来了,常见的滑动冲突,就引申出外部拦截和内部拦截的处理方式。
外部拦截(是否拦截的业务逻辑在父viewGroup的onInterceptTouchEvent()方法中处理)
父ViewGroup,重写onInterceptTouchEvent方法,根据业务需要,判断哪些事件是父Viewgroup需要的,需要的话就对该事件进行拦截,然后交由onTouchEvent方法处理,若不需要,则不拦截,然后传递给子view或子viewGroup。
![](https://img.haomeiwen.com/i5014890/17756206ea2264f7.png)
内部拦截(是否拦截的业务逻辑在子view的dispatchTouchEvent()方法中处理)
子view中拦截事件,父viewGroup默认是不拦截任何事件的,所以,当事件传递到子view时, 子view根据自己的实际情况来,如果该事件是需要子view来处理的,那么子view就自己消耗处理,如果该事件不需要由子view来处理,那么就调用getParent().requestDisallowInterceptTouchEvent()方法来通知父viewgroup来拦截
![](https://img.haomeiwen.com/i5014890/21be2c5ba7290e1c.png)
网友评论