Android开发艺术探索学习笔记3——View的事件体系
学习的同时参看我的《安卓自定义控件常用对象及方法
》
http://blog.csdn.net/u011486491/article/details/54286415#t7
View的基础知识
1、View的位置参数2、MotionEvent3、TouchSlop 4、VelocityTracker 5、GestureDector 6、Scroller对象
View的位置参数
MotionEvent
一次手指点击会触发一系列点击事件。
点击,松开:Down->Up
点击屏幕,移动,松开:Down->Move->Up
TouchSlop
它是系统所能识别的被认为是滑动最小距离。这个值在不同系统上是不同的。
VelocityTracker
这里测量的单位为:像素/(设置的ms单位);有正负之分;可以测量垂直滑动速度和水平滑动速递。
GestureDetector
用来辅助用户检测单击、滑动、长按、双击等行为。
它接管了目标View的OnTouchEvent方法。
GestureDetector中提供了很多方法,我们都可以在onTouchEvent中自己实现,但是对于监听双击的行为,就用GestureDetector。
Scroller:
它解决了ScrollTo和ScrollBy的平滑滑动。
它的使用的典型代码是固定的:
View的滑动:
View的滑动可通过三种方式:1、通过View本身提供的ScrollTo/ScrollBy方法 2、通过动画给View施加平移效果来实现 3、通过改变View的LayoutParams使得View重新布局实现滑动
ScrollTo/ScrollBy
他们滑动的单位为像素。
正方向:
scrollBy方法其内部最终调用的还是scrollTo方法。
使用动画
为了能兼容3.0以下版本的,我们采用nineoldandroids库。
采用补间动画并不能真正改变View位置,这导致点击只能点击其原来的位置。
采用属性动画能够解决这个问题。属性动画除了使用ObjectAnimator之外nineoldandroids库提供了ViewHleper来简化属性动画。
改变布局参数
通过改变View中的LayoutParams来改变布局的位置。
这种方法虽然麻烦但是比较灵活
总结
scrollTo/scrollBy:操作简单,适合对View内容的滑动
动画:操作简单,适合没有交互的复杂动画效果
改变布局:操作复杂,适合有交互的View
弹性滑动
Scroller
通过ScorllTo/ScrollBy滑动View比较生硬,为了避免该问题,我们采用Scroller来解决。
Scroller的核心:在computeScroll()方法中调用invalidate(),在invalidate中又去调用computeScroll();从而实现连贯的View的位移。在computeScroll()内部调用的移动方法依然是scrollTo方法
动画
对于动画来说本身就带有弹性效果。
但是对于一些奇怪的动画效果:
我们可以采用值动画来搞定:ValueAnimator。
采用延时策略
就是通过Handler+scrollTo来控制View的移动。
View的事件分发机制
基础事件传递
onTouch、onTouchEvent和onClickListener优先级
由此可见优先级为
onTouch>onTouchEvent>onClickListener
事件传递序列
一个点击事件产生后:
Activity->Window->View
如果所有元素都不处理这个事件,那么这个事件最终传递给Activity处理。
结论总结:
1、 事件始于down止于up
2、 一个事件序列只能被一个View连接消耗
3、 一旦一个View决定拦截,那么同类型的事件他都将处理,而不再调用onInterceptTouchevent(同类型是指Down、Up、Move)
4、 事件传递过程总是从父控件分发给子控件,通过requestDisallowInterceptTouchEvent可以在子控件干预父控件分发过程。
View的滑动冲突
常见的滑动冲突
不同方向的冲突
同方向的冲突
上面情况的嵌套。
解决方法:
这里我们通过外部拦截法和内部拦截法,并制定相应的规则就可以解决。
外部拦截法:
经过父容器的拦截处理,如果父容器需要就拦截,不需要就向下传递。
这里是在onInterTouchEvent
内部拦截法:
父容器不拦截,全部由子元素判断。如果子元素不消耗事件,通过requestDisallowInterceptTouchEvent让父容器能重新去处理事件。
这个方法控制着父控件的onInterceptTouchEvent是否调用。
这里是在dispatchTouchEvent中处理: