View虽然不是四大组建,但是其作用却不属于四大组建,甚至凌驾于ContentProvider和BroadcastReceiver之上。所以从这节开始讲解一下View的相关知识。
View是Android中所有控件的基类,所以View是一种界面层的控件的一种抽象,它代表了一个控件。除了View,还有一个ViewGroup,即控件组。这两者的关系就是ViewGroup是继承了View,但是ViewGroup也是一个View。
View的位置是有四个顶点来确定的,分别对应于View的四个属性:left、right、top、bottom,其中left是左上角顶点的横坐标,top是左上角的中坐标,right是右下角的横坐标,bottom是右下角的中坐标。需要注意的是:这四个属性都是相对于View的父容器来说的;x轴和y轴的正方向分别是向右和向下。
通过上面的了解我们就很容易就能得出View的长和宽了:
width=right-left; high=bottom-top;
从Android 3.0开始,View增加了几个额外的参数:x、y、translationX和translationY,其中x和y是View左上角的坐标,而translationX和translationY是View左上角相对于父容器的偏移量。这几个参数都是相对于父容器的的坐标,并且translationX和translationY的默认值都是0。这几个参数都可以通过get方法来获取。
当View在平移过程中,top和left表示的是原始左上角的位置信息,其值并不会发生改变,此时发生改变的是x、y、translationX和translationY(下一篇View的移动中会介绍)。
在手指接触屏幕后会产生一系列事件,典型的有以下几种:
ACTION_DOWN:手指刚接触屏幕,即按下
ACTION_MOVE:手指在屏幕上移动
ACTION_UP:手指从屏幕上离开
当手指触摸屏幕时,我们可以通过MotionEvent对象来获取到当前手指在屏幕上的位置,即x和y坐标。系统也提供了两组方法:getX/getY和getRawX/getRawY。getX/getY是返回相对于当前View左上角的x和y,而getRawX/getRawY是相对于手机屏幕左上角的x和y坐标。
TouchSlop是系统所能识别的最小移动距离。当手指的移动距离小于TouchSlop时,系统是认为没有滑动的,只有当手指的移动距离大于TouchSlop时才是移动。TouchSlop是一个常量,跟手机设备有关,不同的设备这个值可能也是不一样的。开发中我们也能通过这个方式获取到这个常量:ViewConfiguration.get(getContext()).getScaledTouchSlop();
VelocityTracker是速度追踪,用于追踪手指在屏幕上滑动过程中的速度,包括水平和竖直方向的速度。
用法如下:
VelocityTracker velocityTracker = VerlocityTracker.obtain();
velocityTracker.addMovement(event);
velocityTracker.computeCurrentVelocity(1000);
int xVelocity = (int) velocityTracker.getXVelocity();
int yVelocity = (int) velocityTracker.getYVelocity();
需要注意的是:获取速度之前必须先计算速度,即必须先调用computeCurrentVelocity方法;还有就是这里的速度是指一段时间内手指所滑过的像素点。当我们不用的时候还需要调用clear方法来重置并回收内存:
velocityTracker.clear();
velocityTracker.recycle();
GestureDetector是手势检测,用户辅助检测用户的单击、滑动、长按、双击等行为。
用法如下:
GestureDetector gestureDetector = new GestureDetector(context);
//解决长按屏幕后无法拖动的现象
gestureDetector.setIsLongpressEnabled(false);
在待监听的View的onTouchEvent方法中添加如下实现:
boolean consume = gestureDetector.onTouchEvent(event);
return consume;
做完上面两步就可以实现GestureDetector的onGestureListener接口和OnDoubleTapListener接口中的方法了。
在日常开发中比较常用的方法有:onSingleTapUp(单击)、onFling(快速滑动)、onScroll(拖动)、onLongPress(长按)和onDoubleTap(双击)。
Scroller弹性滑动对象,用于实现View的弹性滑动。当我们用View的scrollTo/scrollBy方法进行滑动的时候,其过程都是瞬间完成的,这个没有过渡效果,体验非常差。而用Scroller来实现则不是。Scroller本身无法让View弹性滑动,它需要和View的computeScroll方法配合使用才能完成这个功能。
用法如下:
Scroller scroller = new Scroller(context);
//缓慢滚动到指定位置
private void smoothScrollTo(int destX, int destY){
int scrollX = getScrollX();
int delta = destX - scrollX;
//1000ms内滑向destX
scroller.starScroll(scrollX, 0, delta, 0, 1000);
invalidate();
}
@Override
public void computeScroll(){
if(scroller.computeScrollOffset()){
scrollTo(scroller.getCurrX(), scroller.getCurrY());
postInvalidate();
}
}