View的位置参数:
- event.getX():表示的是触摸的点距离自身左边界的距离;
- event.getRawY():表示的是触摸点距离屏幕上边界的距离;
- View.getLeft():子View的左边界到父View的左边界的距离;
- View.getTranslationX():表示在X轴的偏移量。初始值为0,向左偏移为负,向右偏移为正。
View在平移过程中,View.getLeft()的值不会改变,此时改变的是translationX和View的坐标值。
View的左上角x坐标 = View.getLeft() + View.getTranslationX();
TouchSlop:系统所能识别出的最小滑动距离,该值和设备有关。
int touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
VelocityTracker: 表示手指在滑动过程中的速度(pix/ms),包括水平方向和竖直方向的速度。
//初始化
VelocityTracker velocityTracker = VelocityTracker.obtain();
@Override
public boolean onTouchEvent(MotionEvent event) {
velocityTracker.addMovement(event);//速度追踪
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
//获取1000ms内的平均速度(从右向左滑动时,水平方向速度为负值)
velocityTracker.computeCurrentVelocity(1000);
int xVelocity = (int) velocityTracker.getXVelocity();
Log.d("test", "xVelocity=" + xVelocity);
break;
}
velocityTracker.clear();
//velocityTracker.recycle();
return super.onTouchEvent(event);
}
GestureDetector:手势检测,用于检测用户的单击、滑动、长按、双击等行为。
//初始化,参数宜继承SimpleOnGestureListener类,根据需要重写父类方法。
GestureDetector gestureDetector = new GestureDetector(context,
new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2,
float velocityX, float velocityY) {
//可在此判断左滑还是右滑
return super.onFling(e1, e2, velocityX, velocityY);
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
return super.onScroll(e1, e2, distanceX, distanceY);
}
});
//在onTouchEvent方法内监听事件处理
gestureDetector.onTouchEvent(event);
- onScroll:手指按下屏幕并拖动,由一个ACTION_DOWN、多个ACTION_MOVE事件触发,这是拖动行为。在拖动过程中onScroll会反复被调用。
- onFling:手指按下触摸屏、快速滑动后松开,由1个ACTION_DOWN、多个ACTION_MOVE和1个ACTION_UP触发,这是快速滑动行为。在一次滑动中onFling被调用一次,适合在此方法中处理手势相关操作。
Scroller:用于实现View的弹性滑动,提升滑动过渡效果。
一般用于scrollTo/scrollBy方法,需要和View.computeScroll()配合完成View的弹性滑动。
Scroller scroller = new Scroller(context);//初始化
/**
* 弹性滑动到指定位置
*
* @param x
* @param y
*/
public void smoothScrollTo(int x, int y) {
//根据提供的初始位置、滑动距离和持续时间弹性滑动
scroller.startScroll(getScrollX(), getScrollY(),
x - getScrollX(), y - getScrollY(), 2000);
invalidate();
}
/**
* Scroller类滑动原理(针对view内容的滑动)
* 1.invalidate()会促使view的重绘;
* 2.view的重绘会在draw方法中调用computeScroll();
* 3.外部重写computeScroll(),通过scrollTo将view内容滑动到相应位置,
* 并调用postInvalidate触发重绘,123循环执行;
*/
@Override
public void computeScroll() {
super.computeScroll();
//类似插值器,true表示滑动未结束,继续滑动
if (scroller.computeScrollOffset()) {
scrollTo(scroller.getCurrX(), scroller.getCurrY());
postInvalidate();
}
}
view.smoothScrollTo(-500,-500);//外部调用
scrollTo/scrollBy:将View中的内容滑动到相应的位置或距离,正值向左移动,负值向右移动(不改变View的位置)。
view.scrollTo(100,0);//将view中的内容移动到(100,0)位置。
view.scrolloBy(100,0);//将view中的内容x方向移动了100pix。
public void scrollBy(int x, int y) {
//mScrollX是view在x方向的偏移量
scrollTo(mScrollX + x, mScrollY + y);
}
实现View的滑动的常见思路:
- 通过View本身提供的scrollTo/scrollBy方法实现滑动。
场景:适合对View内容的滑动。 - 通过动画给View施加平移效果来实现滑动。
场景:适合没有交互的View、简单些的动画效果。 - 通过改变View的LayoutParams使得View重新布局从而实现滑动。
场景:适合有交互的View。
//2.采用动画实现2000ms内横向滑动500pix
ObjectAnimator.ofFloat(view, "translationX", 0, 500)
.setDuration(2000)
.start();
//3.设置布局参数实现滑动
ViewGroup.MarginLayoutParams params =
(ViewGroup.MarginLayoutParams) t.ok.getLayoutParams();
params.leftMargin += 5;
t.ok.requestLayout();
t.ok.setLayoutParams(params);
View的弹性滑动是将一次大的滑动分成若干次小的滑动并在一个时间段内完成,提升交互体验。一般采用Scroller、Handler#postDelayed以及Thread#sleep等。