您的位置:首页 > 其它

Scroller的方法startScroll、fling、computeScrollOffset

2016-07-12 13:07 381 查看
最近在使用开源库TableFixHeaders(https://github.com/InQBarna/TableFixHeaders),对于其中Scroller的用法不清楚,故看看这几个方法干了什么。

点与点之间的计算 + 触摸事件的分发。

1. startScroll

当startScroll执行过程中即在duration时间内,computeScrollOffset 方法会一直返回false,但当动画执行完成后会返回返加true.

如果不设置duration,默认DEFAULT_DURATION = 250.

public void startScroll(int startX, int startY, int dx, int dy, int duration) {
mMode = SCROLL_MODE;
mFinished = false;
mDuration = duration;
mStartTime = AnimationUtils.currentAnimationTimeMillis();
mStartX = startX;
mStartY = startY;
mFinalX = startX + dx;
mFinalY = startY + dy;
mDeltaX = dx;
mDeltaY = dy;
mDurationReciprocal = 1.0f / (float) mDuration;
}


看代码,这个方法就是把需要滚动的参数传进来。

2.fling

public void fling(int startX, int startY, int velocityX, int velocityY,
int minX, int maxX, int minY, int maxY) {
// Continue a scroll or fling in progress
if (mFlywheel && !mFinished) {
float oldVel = getCurrVelocity();

float dx = (float) (mFinalX - mStartX);
float dy = (float) (mFinalY - mStartY);
float hyp = (float) Math.hypot(dx, dy);

float ndx = dx / hyp;
float ndy = dy / hyp;

float oldVelocityX = ndx * oldVel;
float oldVelocityY = ndy * oldVel;
if (Math.signum(velocityX) == Math.signum(oldVelocityX) &&
Math.signum(velocityY) == Math.signum(oldVelocityY)) {
velocityX += oldVelocityX;
velocityY += oldVelocityY;
}
}

mMode = FLING_MODE;
mFinished = false;

float velocity = (float) Math.hypot(velocityX, velocityY);

mVelocity = velocity;
mDuration = getSplineFlingDuration(velocity);
mStartTime = AnimationUtils.currentAnimationTimeMillis();
mStartX = startX;
mStartY = startY;

float coeffX = velocity == 0 ? 1.0f : velocityX / velocity;
float coeffY = velocity == 0 ? 1.0f : velocityY / velocity;

double totalDistance = getSplineFlingDistance(velocity);
mDistance = (int) (totalDistance * Math.signum(velocity));

mMinX = minX;
mMaxX = maxX;
mMinY = minY;
mMaxY = maxY;

mFinalX = startX + (int) Math.round(totalDistance * coeffX);
// Pin to mMinX <= mFinalX <= mMaxX
mFinalX = Math.min(mFinalX, mMaxX);
mFinalX = Math.max(mFinalX, mMinX);

mFinalY = startY + (int) Math.round(totalDistance * coeffY);
// Pin to mMinY <= mFinalY <= mMaxY
mFinalY = Math.min(mFinalY, mMaxY);
mFinalY = Math.max(mFinalY, mMinY);
}


3. computeScrollOffset

功效:返回值为boolean,true说明滚动尚未完成,false说明滚动已经完成。

参考网址:http://www.cnblogs.com/tt_mc/p/3585390.html

public boolean computeScrollOffset() {
if (mFinished) {
return false;
}

int timePassed = (int)(AnimationUtils.currentAnimationTimeMillis() - mStartTime);

if (timePassed < mDuration) {
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 {
mCurrX = mFinalX;
mCurrY = mFinalY;
mFinished = true;
}
return true;
}


timePassed表示滚动进行到的时间,若滚动未结束,分SCROLL_MODE和FLING_MODE两种情况计算当前位置。

SCROLL_MODE下,

时间最小单位mDurationReciprocal = 1.0f / (float) mDuration;

通过差值器mInterpolator确定距离百分比,这里x和y方向使用同一差值器。

mInterpolator = new ViscousFluidInterpolator(); 是Scroller的静态内部类,取值算法见getInterpolation()所调用的viscousFluid()。

static class ViscousFluidInterpolator implements Interpolator {

/* Controls the viscous fluid effect (how much of it). /

private static final float VISCOUS_FLUID_SCALE = 8.0f;

private static final float VISCOUS_FLUID_NORMALIZE;
private static final float VISCOUS_FLUID_OFFSET;

static {

// must be set to 1.0 (used in viscousFluid())
VISCOUS_FLUID_NORMALIZE = 1.0f / viscousFluid(1.0f);
// account for very small floating-point error
VISCOUS_FLUID_OFFSET = 1.0f - VISCOUS_FLUID_NORMALIZE * viscousFluid(1.0f);
}

private static float viscousFluid(float x) {
x *= VISCOUS_FLUID_SCALE;
if (x < 1.0f) {
x -= (1.0f - (float)Math.exp(-x));
} else {
float start = 0.36787944117f;   // 1/e == exp(-1)
x = 1.0f - (float)Math.exp(1.0f - x);
x = start + x * (1.0f - start);
}
return x;
}

@Override
public float getInterpolation(float input) {
final float interpolated = VISCOUS_FLUID_NORMALIZE * viscousFluid(input);
if (interpolated > 0) {
return interpolated + VISCOUS_FLUID_OFFSET;
}
return interpolated;
}


}

FLING_MODE下,

x和y还是同比例变化,这里设定了采样率NB_SAMPLES = 100;(??)

index和index+1的含义?

速度因子,velocityCoef = (d_sup - d_inf) / (t_sup - t_inf);

距离因子,distanceCoef = d_inf + (t - t_inf) * velocityCoef;

4. invalidate() 与 postInvalidate()

5.smoothScrollBy() 与 fling()

6. 其他相关类

参考网址:http://mobile.51cto.com/design-375889.htm

http://www.cnblogs.com/wanqieddy/archive/2012/05/05/2484534.html

VelocityTracker 速度追踪器

追踪用户手指在屏幕上的滑动速度。当你要跟踪一个touch事件的时候,使用obtain()方法得到这个类的实例,然后 用addMovement(MotionEvent)函数将接受到的motionEvent加入到VelocityTracker类实例中。

使用computeCurrentVelocity(int)初始化速率的 单位,并获得当前的事件的速率;然后使用getXVelocity() 或getXVelocity()获得横向和竖向的速率。

ViewConfiguration

定义了android的许多标准的常量(UI的超时、大小和距离等)。

public int getScaledEdgeSlop() 获得一个触摸移动的最小像素值。也就是说,只有超过了这个值,才代表我们该滑屏处理了。

public static int getLongPressTimeout() 获得一个执行长按事件监听(onLongClickListener)的值。也就是说,对某个View按下触摸时,只有超过了这个时间值在,才表示我们该对该View回调长按事件了;否则,小于这个时间点松开手指,只执行onClick监听。

GestureDetector 手势识别器

追踪用户手指在屏幕上的滑动方向
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: