Scroller封装了滑动过程,当你需要实现一个滑动动画的时候,可以使用Scroller或是OverScroller类采集数据。例如,为了处理fling手势,随着时间的推移,Scrollers记录着滑动的偏移量,但是Scroller不会主动向View上报它的坐标。开发者需要以一定的频率主动向Scroller获取坐标,这样才能保证实现平滑滑动动画。
例如:
private Scroller mScroller = new Scroller(context);//实例化一个Scroller对象
public void zoomIn(){
mScroller.forceFinished(true);//强制停止Scroller滑动
mScroller.startScroll(0, 0, 100, 0);//此方法只是启动开始滑动的位置,实际并没有执行滑动过程
invalidate();//invalidate会导致View重绘
}
使用computeScrollOffset()方法,跟踪x/y坐标的变化。computeScrollOffset()方法返回一个布尔值,来标识滑动是不是已经停止。如果没有停止,则意味着fling动作还在执行中。如果滑动没有停止,则返回true,如果滑动已经停止,则返回false。可以使用Scroller.getCurrX()和Scroller.getCurrY()方法来获取当前x/y坐标的偏移量。
例如:
if (mScroller.computeScrollOffset()){
int currX = mScroller.getCurrX();
int currY = mScroller.getCurrY();
}
computeScrollOffset()函数详解:
当需要获取滑动过程中新的坐标值时,调用此方法,如果此方法返回true,则说明滑动过程尚未停止
public boolean computeScrollOffset() {
if (mFinished) {//如果滑动已经停止,则直接返回false
return false;
}
int timePassed = (int)(AnimationUtils.currentAnimationTimeMillis() - mStartTime);//获取从开始滑动到现在经过了多长时间
if (timePassed < mDuration) {//如果滑动的时间小于startScroll()函数设置的滑动时间
switch (mMode) {//根据滑动的不同类型,得到此时当前坐标的值
case SCROLL_MODE:
final float x = mInterpolator.getInterpolation(timePassed * mDurationReciprocal);
mCurrX = mStartX + Math.round(x * mDeltaX);
mCurrY = mStartY + Math.round(x * mDeltaY);
break;
case FLING_MODE:
final float t = (float) timePassed / mDuration;
final int index = (int) (NB_SAMPLES * t);
float distanceCoef = 1.f;
float velocityCoef = 0.f;
if (index < NB_SAMPLES) {
final float t_inf = (float) index / NB_SAMPLES;
final float t_sup = (float) (index + 1) / NB_SAMPLES;
final float d_inf = SPLINE_POSITION[index];
final float d_sup = SPLINE_POSITION[index + 1];
velocityCoef = (d_sup - d_inf) / (t_sup - t_inf);
distanceCoef = d_inf + (t - t_inf) * velocityCoef;
}
mCurrVelocity = velocityCoef * mDistance / mDuration * 1000.0f;
mCurrX = mStartX + Math.round(distanceCoef * (mFinalX - mStartX));
// Pin to mMinX <= mCurrX <= mMaxX
mCurrX = Math.min(mCurrX, mMaxX);
mCurrX = Math.max(mCurrX, mMinX);
mCurrY = mStartY + Math.round(distanceCoef * (mFinalY - mStartY));
// Pin to mMinY <= mCurrY <= mMaxY
mCurrY = Math.min(mCurrY, mMaxY);
mCurrY = Math.max(mCurrY, mMinY);
if (mCurrX == mFinalX && mCurrY == mFinalY) {
mFinished = true;
}
break;
}
}
else {//执行滑动的时间已经不小于startScroll()函数设置的滑动时间小,说明滑动已经停止
mCurrX = mFinalX;//把当前坐标设置为startScroll()函数设置的滑动最终位置的坐标
mCurrY = mFinalY;
mFinished = true;
}
return true;
}