Android Scroller和VelocityTracker类
1. scrollXX()方法
scrollTo()
和scrollBy
()是用于滑动View
中的内容
scrollTo(int x, int y) // 将View中内容滑动到相应的位置
scrollBy(int x, int y) // 将View中内容滑动相对的位置
对于一个View
来说,有一个View
视图和一个Canvas
。滑动时会移动View
视图,显示不同的Canvas
部分。
下面例子中,黑框是View
视图,黄色是Canvas
。
x,y大于0时,View
视图向右下移动。
x,y小于0时,View
视图向左上移动。
2. Scroller类
Scroller
类是为了实现View
平滑滑动的一个帮助类。
Scroller.getCurrX() //获取Scroller当前水平滑动的位置
Scroller.getCurrY() //获取Scroller当前竖直滑动的位置
// 滑动,startX、startY为开始滑动的位置,dx、dy为滑动的偏移量, duration为完成滑动的时间
Scroller.startScroll(int startX, int startY, int dx, int dy) // 使用默认完成时间250ms
Scroller.startScroll(int startX, int startY, int dx, int dy, int duration)
下面是一个回滚到原点的例子,调用startScroll()
方法,并且覆盖computeScroll()
方法。
// 移动到原点
public void backToOrigin(int scrollX, int scrollY) {
mScroller.startScroll(scrollX, scrollY, -scrollX, -scrollY, 1000);
postInvalidate();
}
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
postInvalidate();
}
}
3. VelocityTracker类
VelocityTracker
类用于对触摸点的速度跟踪,方便获取触摸点的速度。
// 添加触摸对象MotionEvent,用于计算触摸速率。
addMovement(MotionEvent event)
// 获得当前的事件的速率,1毫秒运动了多少个像素的速率,units为1000时表示1秒
computeCurrentVelocity(int units, float maxVelocity)
创建应用,在dispatchTouchEvent(MotionEvent)
方法中捕捉触摸点。在onTouchEvent(MotionEvent)
方法中滑动界面。mMaxVelocity
和mTouchSlop
从ViewConfiguration
类中获取
private Scroller mScroller;
private VelocityTracker mVelocityTracker;
private int mDownX;
private boolean mSlide;
private int mMaxVelocity;
private int mTouchSlop;
public VelocityTrackerView(Context context) {
this(context, null);
}
public VelocityTrackerView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
mScroller = new Scroller(context);
ViewConfiguration configuration = ViewConfiguration.get(context);
mMaxVelocity = configuration.getScaledMaximumFlingVelocity();
mTouchSlop = configuration.getScaledTouchSlop();
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch(ev.getAction()) {
case MotionEvent.ACTION_DOWN:
mDownX = (int) ev.getX();
// 请求一个新的VelocityTracker
acquireVelocityTracker(ev);
break;
case MotionEvent.ACTION_MOVE:
if (mVelocityTracker != null) {
// 添加触摸对象
mVelocityTracker.addMovement(ev);
// 计算当前速率
mVelocityTracker.computeCurrentVelocity(1000, mMaxVelocity);
final float velocityX = mVelocityTracker.getXVelocity();
if (Math.abs(velocityX) > 600 &&
Math.abs(ev.getX() - mDownX) > mTouchSlop) {
mSlide = true;
}
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
if (mSlide) {
// 回到初始位置
backToOrigin(mDownX - (int) ev.getX(), 0);
mSlide = false;
}
if (mVelocityTracker != null )
releaseVelocityTracker();
break;
}
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch(event.getAction()) {
case MotionEvent.ACTION_MOVE:
if (mSlide) {
scrollTo(mDownX - (int) event.getX(), 0);
}
break;
}
return true;
}
private void acquireVelocityTracker(final MotionEvent event) {
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
}
mVelocityTracker.addMovement(event);
}
private void releaseVelocityTracker() {
if (mVelocityTracker != null) {
mVelocityTracker.clear();
mVelocityTracker.recycle();
mVelocityTracker = null;
}
}
效果如下
4. ViewConfiguration类
ViewConfiguration
类主要使用了下面三个方法
getScaledTouchSlop() // 获得能够进行手势滑动的距离
getScaledMinimumFlingVelocity() // 获得允许执行一个fling手势动作的最小速度值
getScaledMaximumFlingVelocity() // 获得允许执行一个fling手势动作的最大速度值