-
3.1 View的基础知识
-
1.View:
View是Android中所有控件的基类(和java中的Object相似),它是一种界面层控件的抽象。ViewGroup也是继承自View的,它们相互嵌套,形成了View树结构。
-
2.View的位置参数:
top、left、right、bottom,分别对应View的左上角和右下角相对于父容器的横纵坐标值。
从Android 3.0开始,view增加了x、y、translationX、translationY四个参数,这几个参数也是相对于父容器的坐标。x和y是左上角的坐标,而translationX和translationY是view左上角相 对于父容器的偏移量,默认值都是0。 x = left + translationX y = top + translationY 注意:在进行平移操作的时候,top、left、right、bottom不会改变,还是原始位置的值,x、y、translationX、translationY则会跟随移动改变。-
3.MotionEvent和TouchSlop
-
3.1. MotionEvent
MotionEvent是指手指接触屏幕后所产生的一系列事件,主要有ACTION_UP、ACTION_DOWN、ACTION_MOVE等。正常情况下,一次手指触屏会触发一系列点击事件,主要有下面两种典型情况:
1.点击屏幕后离开,事件序列是ACTION_DOWN -> ACTION_UP; 2.点击屏幕后滑动一会再离开,事件序列是ACTION_DOWN -> ACTION_MOVE -> ACTION_MOVE -> … -> ACTION_UP; 通过MotionEvent可以得到点击事件发生的x和y坐标,其中getX和getY是相对于当前view左上角的x和y坐标,getRawX和getRawY是相对于手机屏幕左上角的x和y坐标。-
3.2. TouchSlop
TouchSlope是系统所能识别出的可以被认为是滑动的最小距离,获取方式是ViewConfiguration.get(getContext()).getScaledTouchSlope()。查看源码发现这个值是8dp。实际使用的时候,可以拿到这个值来判断是否是滑动。
-
4. VelocityTracker、GestureDetector、Scroller
-
4.1. VelocityTracker
VelocityTracker用于追踪手指在滑动过程中的速度,包括水平和垂直方向上的速度。
速度计算公式: 速度 = (终点位置 - 起点位置) / 时间段 使用过程: 1.在View的OnTouch方法中追踪当前单击事件的速度 2.获得当前速度:获得之前必须计算,也就是调用mVelocityTracker.computeCurrentVelocity(时间ms);这里的速度是指单位时间内的速度,计算公式如上所示。 3.不需要的时候重置回收-
4.2 GestureDetector
GestureDetector用于辅助检测用户的单击、滑动、长按、双击等行为。GestureDetector的使用比较简单,主要也是辅助检测常见的触屏事件。作者建议:如果只是监听滑动相关的事件在
onTouchEvent中实现;如果要监听双击这种行为的话,那么就使用GestureDetector。 使用过程: 1.创建对象实现接口 2.接管View的OnTouchEvent事件 3. 选择性实现接口中的方法:列举使用较多的-
4.3 Scroller
弹性滑动对象,用于实现View的弹性滑动。
在下面使用Scroller进行弹性滑动会再说。 常见实现实例:参考:View滑动效果的七种实现方式 http://blog.csdn.net/zly921112/article/details/50436538
详细内容可以参见《Android群英传》读书笔记 (2) 第五章 Scroll分析
-
3.2 View的滑动
不管多么绚丽的滑动效果,最终都是由不通过的滑动加特效组成的。掌握滑动的方法是实现绚丽的自定义控件的基础。目前有三种常见方式可以实现控件的滑动:控件本身提供的scrollTo/scrollBy、动画效果、改变View的LayoutParams使用View重新布局从而实现滑动。
-
3.2.1控件本身提供的scrollTo/scrollBy
源码分析:
源码看出来,一个是滑动到指定位置(绝对位置),一个是做增量滑动。在滑动过程中,要十分注意,这个坐标系计算方式有点奇葩,由于我们scrollTo/scrollBy滑动的是内容,而不是View本身(如果是一个ViewGroup那么就是所有子控件移动了)。所以就导致内容区域向右上滑动是负数,另外怎么滑动也无法将View滑动到附近其它View的区域,超滑动到其它View就超出父ViewGroup了,超出部分就不会显示。 具体可以参考: 这篇博客关于这个讲的很不错,另外可以参考《android群英传》94页分析的也很好 android 布局之滑动探究 scrollTo 和 scrollBy 方法使用说明 http://blog.csdn.net/vipzjyno1/article/details/24577023-
3.2.2使用动画
传统的动画作用的是View的影像,View本身并没有什么移动,动画完成之后FillAfter设置true停在最后一刻。而Android3.0之后出的属性动画则可以移动View本身。帧动画可以做的事情属性动画都可以做到,但是3.0以下的想用就需要动画库的支持包了。
传动的动画做完之后由于View没动,所以会有很大问题,常见的就是点击事件还在原来的位置上面。艺术探究上对于这个问题有个思路,在动画结束位置准备一个一样的控件,动画完了显示出来,隐藏原来的。不过有点麻烦,还是用属性动画吧,3.0以下现在用的也少。补充阅读参考:
书籍::《Android群英传》第7章 博客:android 动画分类 http://blog.csdn.net/xyz_lmn/article/details/38667899-
3.2.3 改变布局参数
这里直接拿到LayoutParams做相应改变就可以了
-
3.2.4 三种方式的对比
第一种,原生方法,专门用于滑动,可以轻松滑动而且不影响布局内部元素的点击事件,但是只能滑动内容而不能滑动View本身。
第二种,动画,属性动画比较完美,View本身也可以操作。但是另外二种动画(3.0以下的),不能改变View本身的位置,不适合有交互的View。动画的优点在于,可以实现某些较为复杂的动画效果。 第三种,直接改参数,适合有交互的View。-
3.3弹性滑动
实现弹性滑动有一个共同的思想:渐进式滑动,都是将一次大的滑动分成若干次小的滑动并且在一个时间段内完成。常见的有三种实现方式:Scroller、Handler#postDelayed、Thread#sleep.
-
3.3.1 Scroller
代码清单:
我们构建了mScroller对象之后,调用StartScroll(),源码如下,还没有做什么操作,只是保存了一些数据。 之后调用invalidate()进行刷新,动画开始了,invalidate()之后会调用onDraw()方法,onDraw()会调用到,computeScroll()方法,这个是一个空实现,上面我们实现了,拿到当前父视图中content的滑动坐标。接着继续刷新。循环知道完成动画-
3.3.2 通过动画
动画本身就天然具有渐进性,使用就有弹性。书中例子:用属性动画模仿Scroller
-
3.3.3 使用延时策略
发送一系列延时消息,达到一种渐进式效果。可以使用Handler和View的postDelayed来实现,通过不断的循环给自己发消息,达到效果,记得要有出口,不然就是死循环了。
常见使用实例:这里在界面退出的时候,最好是把消息remove掉,不然后台还是会继续循环操作,在Android中常见的自动轮播图,就可以使用这种策略来做,这个就必须在界面退出时候移除了。
未完待续。。。。