Android开发艺术探索学习笔记3——View的事件体系

来源:互联网 发布:斯米诺黑牌伏特加知乎 编辑:程序博客网 时间:2024/06/04 09:32

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中处理:

 

 

 

 

 

 

 

阅读全文
0 0
原创粉丝点击