位置参数
View的位置主要由它的四个顶点来决定,分别对应于View的四个属性:top、left、right、bottom.
其中top是左上角的纵坐标,left是左上角的横坐标,right是右下角的横坐标,bottom是右下角的纵坐标.(注:这些坐标都是相对于父容器所说,为相对坐标)

View的宽高和坐标的关系:
width = right - left;
height = bottom - top;
在代码中获取四个位置参数:
top = getTop();
left = getLeft();
right = getRight();
bottom = getBottom();
从3.0之后开始,Android增加了几个参数:x、y、translationX、translationY,并且都是相对父容器的的坐标,其中x和y是View左上角的坐标.translationX和translationY是View左上角相对于父容器的偏移量,且默认值都为0.
left = x - translationX;
top = y - translationY;
注:在View的平移过程中,top和left始终表示的是其原始左上角的位置信息,不会发生改变,改变的是x、y、translationX和translationY.
MotionEvent
典型事件
手指接触屏幕后所产生的一系列事件中,比较重要的有:
- ACTION_DOWN 手指刚接触屏幕
- ACTION_MOVE 手指在屏幕上移动
- ACTION_UP 手指抬起的一瞬间
常见事件序列
- 点击屏幕后抬起 DOWN -> UP
- 点击屏幕后滑动后再抬起 DOWN -> MOVE -> UP
事件信息
通过MotionEvent对象我们可以得到点击事件发生的x和y坐标.
- getX()、getY() 相对于当前View左上角.
- getRaw()、getY() 相对于手机屏幕左上角
TouchSlop
什么是TouchSlop
TouchSlop是系统所能识别出的最小滑动距离.如果手指在屏幕上滑动小于该距离则系统无法将该动作认定为滑动.
这是一个常量,与设备有关,在不同的设备上这个值可能不同.
获取TouchSlop
int touchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
使用场景
当我们在处理滑动时,可以使用这个常量来进行过滤,当滑动距离小于该值,我们可以认为未达到滑动距离的临界值,不认为它是一次有效的滑动.
VelocityTracker
速度追踪,用于追踪手指在滑动过程中的速度,包括水平速度和竖直方向的速度.
使用过程
在View的onTouchEvent方法中追踪当前单击事件的的速度:
@Override
public boolean onTouchEvent(MotionEvent event) {
VelocityTracker tracker = VelocityTracker.obtain();
tracker.addMovement(event);
tracker.computeCurrentVelocity(1000);//一个时间单元或时间间隔,单位为毫秒
float xVelocity = tracker.getXVelocity();
float yVelocity = tracker.getYVelocity();
return super.onTouchEvent(event);
}
注:获取速度之前必须先计算速度,即getXVelocity和getYVelocity之前必须要调用computeCurrentVelocity方法.这里的速度是指一段时间内手指所滑过的像素数,比如将时间设置为1000ms时,在1s内,手指在水平方向从左向右滑过100像素,那么水平速度就是100.且速度可以为负数,当手指从右向左滑动时,水平方向速度即为负值.
计算公式:
速度 = (终点位置 - 起点位置) / 时间段
当不需要使用后需重置回收.
tracker.clear();
tracker.recycle();
GestureDetector
手势检测,用于辅助检测用户的单击、滑动、长按、双击等行为.
使用方式
创建GestureDetector对象并实现OnGestureListener接口,如果需要监听双击行为还可以实现OnDoubleTapListener接口.并接管onTouchEvent方法.
public class SeanView extends View implements GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener {
GestureDetector detector = new GestureDetector(this);
detector.setIsLongpressEnabled(false);//解决长按屏幕后无法拖动问题
@Override
public boolean onTouchEvent(MotionEvent event) {
boolean consume = detector.onTouchEvent(event);
return consume;
}
}
方法介绍
- OnGestureListener
- onDown 手指接触屏幕的瞬间
- onShowPress 手指接触屏幕的瞬间,尚未松开或拖动
- onSingleTapUp 单击
- onScroll 拖动
- onLongPress 长按
- onFling 快速滑动
- OnDoubleTapListener
- onDoubleTap 双击 与onSingleTapConfirmed互斥
- onSingleTapConfirmed 单击且后续无单击行为
- onDoubleTapEvent 双击
Scroller
用于实现View的弹性滑动.Scroller本身无法让View弹性滑动,它需要和computeScroll方法配合使用.
private Scroller scroller = new Scroller(getContext());
private void smoothScrollTo(int destX, int destY) {
int scrollX = getScrollX();
int delta = destX - scrollX;
scroller.startScroll(scrollX, 0, delta, 1000);
invalidate();
}
@Override
public void computeScroll() {
if (scroller.computeScrollOffset()) {
scrollTo(scroller.getCurrX(), scroller.getCurrY());
postInvalidate();
}
}
网友评论