什么是View
我们都知道,TextView是View,Button也是View,但View不仅仅是一个视图,显示给用户看,还可以与用户交互。LinearLayout是一个ViewGroup,而ViewGroup是View的一个子类,所以也是一个View。ViewGroup和它所包含的一个View组成一个View树结构,这对接下来说到View事件的传递很重要。先有个概念。
View位置参数
要确定给一个View的位置,要知道这个View的left,top,right,bottom,View额外还有x,y,translationX,translationY。
我相信这个图已经很好的解析了left,top,right,bottom的意思了,还指出了Android手机的起始标志(0,0)是手机屏幕的左上角。(其实java swing也是一样的)
x,y是View左上角的坐标。而translationX和translationY指的是View的偏移量。其实是这么一回事
x = translationX + left;
y = translationY + top;
MotionEvent和TouchSlop
MotionEvent这个我们很熟悉了,我们监听onTouch事件时,作为参数给我们使用。MotionEvent常用的一些事件类型,如ACTION_DOWN,ACTION_MOVE,ACTION_UP,其实已经很熟悉了。
MotionEvent的getX()/getY()和getRawX()/getRawY()这个两对方法都是用于获取我们Touch屏幕的坐标,可以这两个坐标是不一样的。
getX()/getY() 获取的是相对于View左上角的x,y坐标。
getRawX()/getRawY() 获取的是相对于手机屏幕左上角的x,y坐标
TouchSlop是我第一次知道一个变量,Android系统用这个变量来判断最小的滑动距离。如果两次滑动之间的距离小于这个变量值,系统会判断不认为你在滑动。这样做为了更好的用户体验。这个值和设备有关,不是一个固定的值。我们可以调用ViewConfiguration.get(getContext()).getScaledTouchSlop()获取这个变量值。我们可以根据这个变量仿Android处理一些滑动。
VelocityTracker
这个类可以追踪手指的速度,一般用在onTouch()方法中使用。
VelocityTracker velocityTracker = VelocityTracker.obtain();
velocityTracker.addMovement(event);
获取当前滑动速度
// 1000是毫秒数,设置单位时间,计算速度,这方法必须先调用
velocityTracker.computeCurrentVelocity(1000);
// 获取x和y方向的滑动速度,其实获取的是单位时间内启动的像素点,所以前面一定要先设置单位时间计算速度
int xVelocity = (int) velocityTracker.getXVelocity();
int yVelocity = (int) velocityTracker.getYVelocity();
GestureDetector
手势监听,检测用户单击,滑动,长按,双击等行为。也可以在onTouch()中使用。
// myOnGestureListener是OnGestureListener的一个实现类
GestureDetector gestureDetector = new GestureDetector(this, myOnGestureListener);
// 解决长按无法拖动问题
gestureDetector.setIsLoogpressEnable();
然后在onTouch()方法内接管View的onTouch事件
boolean consum = gestureDetector.onTouchEvent(event);
return consum;
书中详细列了很多方法,有兴趣可以看书。常用的有一下几种:
- onSingleTapUp(单击)
- onFling(快速滑动)
- onScroll(拖动,我还以为是滑动呢)
- onLongPress(长按)
- onDoubleTap(双击)
Scroller
弹性滑动对象,用于View的弹性滑动。利用View的scrollTo和scrollBy是瞬间滑动,用户体验不好。Scroller就可以实现View的弹性滑动,不过要配合View的computeScroll方法一起用。下面是一段经典的贪心滑动代码。
Scroller scroller = =new Scroller(this);
private void smoothScrollTo(int destX, int destY) {
// 只滑动X
int scrollX = getScrollX();
int scrollY = getScrollY();
int delta = destX - scrollX;
scroller.startScroll(scrollX, scrollY, delta, 0, 1000);
invalidate();
}
@Override
public void computeScroll() {
// 返回ture表示动画没有完成
if (scroll.computeScrollOffset()) {
scrollTo(scroll.getCurrentX(), scroll.getCurrentY());
postInvalidate();
}
}
我们先知道Scroller怎么使用,接下来会知道其原理。