1、View基础
view 是 android 中所有控件的基类 ,view 本身既可以是单个控件也可以是由多个控件组成的一组控件,通过这种关系就形成了 View 树的结构。
1.1、View 的位置参数
View 的位置主要由它的四个顶点来决定,分别相对于 View 的四个属性: top、left、right、bottom。
需要注意的是,这些坐标都是相对于 View 的父容器来说的,因此它是一种相对坐标。
如何得到这四个参数呢?在 View 的源码中它们对应于 mLeft、mRight、mTop、mBottom 这四个成员变量,获取方式如下:
Left = getLeft();
Right = getRight();
Top = getTop();
Bottom = getBottom();
从 Android3.0 开始,View 增加了额外的几个参数:x、y、translationX、translationY,其中 x 和 y 是 View 左上角的坐标,而 translationX 和 translationY 是 View 左上角相对于父容器的偏移量。这几个参数也是相对于父容器的坐标,并且 translationX 和 translationY 的默认值是0,和 View 的四个基本的位置参数一样,View 也为它们提供了 get/set 方法,几个参数的换算关系如下所示:
x = left + translationX
y = top + translationY
需要注意的是,View 在平移过程中,top 和 left 表示的是原始左上角的位置信息,其值并不会发生改变,此时发生改变的是 x、y、translationX 和 translationY 这四个参数。
1.2、 MotionEvent 触摸事件
典型的事件类型有如下几种:
ACTION_DOWN
—————–手指刚接触屏幕ACTION_MOVE
——————手指在屏幕上移动ACTION_UP
——————-手指从屏幕上松开的一瞬间
正常情况下,一次手指触摸屏幕的行为会出发一系列点击事件,考虑如下几种情况:
- 点击屏幕后离开松开,事件序列为 DOWN -> UP;
- 点击屏幕滑动一会再松开,事件序列为 DOWN -> MOVE -> … > MOVE -> UP。
上述情况是典型的时间序列,同时通过 MotionEvent 对象我们可以得到点击事件发生的 x 和 y 坐标。为此,系统提供了两组方法:getX/getY 返回的是相对于当前 View 左上角的 x 和 y 坐标, getRawX/getRawY 返回的是相对于手机屏幕左上角的 x 和 y 坐标。
1.3、TouchSlop 最小滑动距离
TouchSlop 是系统所能够识别出的被认为是滑动的最小距离,就是说,当手指在屏幕上滑动时,如果滑动的距离小于这个常量,那么系统就不认为用户是在进行滑动操作。
这个常量的获取:
ViewConfiguration.get(getContext()).getScaledTouchSlop()
1.4、VelocityTracker 速度追踪
速度追踪,用于追踪手指在滑动过程中的速度,包括水平和竖直方向的速度。
使用方法:
在 View 的 onTouchEvent 方法中追踪当前单击事件的速度:
VelocityTracker velocityTracker = VelocityTracker.obtain(); velocityTracker.addMovement(event);
当我们想知道当前的滑动速度时,采用如下方式:
velocityTracker.computeCurrentVelocity(1000); int xVelocity = (int) velocityTracker.getXVelocity(); int yVelocity = (int) velocityTracker.getYVelocity();
需要注意的是:
- 获取速度之前必须先计算速度,后面参数的单位是ms。
- 这里的速度是指一段时间内手指所滑动的像素数,比如将时间间隔设为 1000ms 时,在1s内手指在水平方向从左到右滑过 100 像素,那么水平速度就是 100。注意速度可以是负数,当手指从右向左滑动是,水平方向速度即为负值。
当不需要使用它的时候,需要调用 clear 方法来重置并回收内存:
velocityTracker.clear(); velocityTracker.recycle();
1.5、GestureDetector 手势检测
用户辅助检测用户的单击、滑动、长按、双击等行为。
使用方式:
创建一个 GestureDetector 对象并实现 onGestureListener 接口,根据需要我们还可以实现 onDoubleTapListener 从而能够监听双击行为:
GestureDetector mGestureDetector = new GestureDetector(this); //解决长按屏幕后无法拖动的现象 mGestureDetector.setIsLongpressEnabled(false);
接管目标 View 的 onTouchEvent 方法,在待监听 View 的 onTouchEvent 方法中添加如下实现:
boolean consume = mGestureDetector.onTouchEvent(event); return consume;
现在就可以有选择地实现 onGestureListener 和 onDoubleTapListener 中的方法了
实际开发中,可以不使用 GestureDetector ,完全可以自己在 View 的 onTouchEvent 方法中实现所需的监听。
1.6、Scroller 弹性滑动对象
用于实现 View 的弹性滑动,当时用 View 的 scrollTo/scrollBy 方法来进行滑动时,其过程是瞬间完成的,没有过渡效果。这个时候既可以使用 Scroller 来实现有过渡效果的滑动。Scroller 本身无法让 View 弹性滑动,它需要和 View 的 computeScroll 方法配合使用才能完成这个功能。如何使用 Scroller:
Scroller scroller = new Scroller(mContext); //缓慢滚动到指定位置 private void smoothScrollTo(int destX, int destY){ int scrollX = getScrollX(); int delta = destX - scrollX; //1000ms内滑向destX,效果就是慢慢滑动 mScroller.startScroller(scrollX, 0, delta, 0, 1000); invalidate(); } @Override public void computeScroll(){ if(mScroller.computeScrollOffset()){ scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); postInvalidate(); } }