Android Scrollerの理解
6508 ワード
Androidの原理を理解するには、ソースコードで分析するのが一番です.今度また来て、Scrollerがいったい何なのか見てみましょう.
Scrollerはスクロールの補助クラスで、Viewの位置と計算された位置だけを格納し、本当にViewを移動していません.嫌いなのはScrollerです.startScroll()は名前から人を誤導していて、最初はこの方法で移動したのかと思っていました.
Scrollerは最初は変数がたくさんあって、名前はいくつかの位置X、Yなどを見ることができて、スクロールの状態、速度の値があります.主な方法もgetXXXとsetXXXで、これが属性を得ることです.
重要な2つの方法は次のとおりです.
これは,与えられた開始と終了のxy値と時間により,対応する時間に対応すべき座標を算出する.いずれも付与された文であり,Viewの移動には触れていない.
もう1つは、
fling、この恐ろしいやつがまた来たが、実は何でもない.指を離した瞬間、Viewの転がりはまだ速度があるので、速度によって次のViewの位置を計算したのだ.
では、このScrollerはVeiwを移動していませんが、何をしますか?これは補助移動で、私たちはいつでもgetCurrXとgetCurrYでViewの位置を得ることができて、それから..このVeiwをスクロールするにはScrollToを使用します.しかし注意しなければならないのは、ScrolToはViewの内容に対して、LinearLayoutであればScrollTo()、Linearlayoutの中のものはすべて移動します.それはTextViewです.ScrollTo()は、TextViewの中身が動いているだけなんですよね~、TextViewはそのまま動いていません.
Scrollerはスクロールの補助クラスで、Viewの位置と計算された位置だけを格納し、本当にViewを移動していません.嫌いなのはScrollerです.startScroll()は名前から人を誤導していて、最初はこの方法で移動したのかと思っていました.
public class Scroller {
private int mMode;
private int mStartX;
private int mStartY;
private int mFinalX;
private int mFinalY;
private int mMinX;
private int mMaxX;
private int mMinY;
private int mMaxY;
private int mCurrX;
private int mCurrY;
private long mStartTime;
private int mDuration;
private float mDurationReciprocal;
private float mDeltaX;
private float mDeltaY;
private boolean mFinished;
private Interpolator mInterpolator;
private boolean mFlywheel;
private float mVelocity;
private float mCurrVelocity;
private int mDistance;
private float mFlingFriction = ViewConfiguration.getScrollFriction();
private static final int DEFAULT_DURATION = 250;
private static final int SCROLL_MODE = 0;
private static final int FLING_MODE = 1;
private static float DECELERATION_RATE = (float) (Math.log(0.78) / Math.log(0.9));
private static final float INFLEXION = 0.35f; // Tension lines cross at (INFLEXION, 1)
private static final float START_TENSION = 0.5f;
private static final float END_TENSION = 1.0f;
private static final float P1 = START_TENSION * INFLEXION;
private static final float P2 = 1.0f - END_TENSION * (1.0f - INFLEXION);
private static final int NB_SAMPLES = 100;
private static final float[] SPLINE_POSITION = new float[NB_SAMPLES + 1];
private static final float[] SPLINE_TIME = new float[NB_SAMPLES + 1];
private float mDeceleration;
private final float mPpi;
// A context-specific coefficient adjusted to physical values.
private float mPhysicalCoeff;
Scrollerは最初は変数がたくさんあって、名前はいくつかの位置X、Yなどを見ることができて、スクロールの状態、速度の値があります.主な方法もgetXXXとsetXXXで、これが属性を得ることです.
重要な2つの方法は次のとおりです.
/**
* Start scrolling by providing a starting point, the distance to travel,
* and the duration of the scroll.
*
* @param startX Starting horizontal scroll offset in pixels. Positive
* numbers will scroll the content to the left.
* @param startY Starting vertical scroll offset in pixels. Positive numbers
* will scroll the content up.
* @param dx Horizontal distance to travel. Positive numbers will scroll the
* content to the left.
* @param dy Vertical distance to travel. Positive numbers will scroll the
* content up.
* @param duration Duration of the scroll in milliseconds.
*/
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;
}
これは,与えられた開始と終了のxy値と時間により,対応する時間に対応すべき座標を算出する.いずれも付与された文であり,Viewの移動には触れていない.
もう1つは、
/**
* Start scrolling based on a fling gesture. The distance travelled will
* depend on the initial velocity of the fling.
*
* @param startX Starting point of the scroll (X)
* @param startY Starting point of the scroll (Y)
* @param velocityX Initial velocity of the fling (X) measured in pixels per
* second.
* @param velocityY Initial velocity of the fling (Y) measured in pixels per
* second
* @param minX Minimum X value. The scroller will not scroll past this
* point.
* @param maxX Maximum X value. The scroller will not scroll past this
* point.
* @param minY Minimum Y value. The scroller will not scroll past this
* point.
* @param maxY Maximum Y value. The scroller will not scroll past this
* point.
*/
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 = FloatMath.sqrt(dx * dx + dy * 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 = FloatMath.sqrt(velocityX * velocityX + velocityY * 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);
}
fling、この恐ろしいやつがまた来たが、実は何でもない.指を離した瞬間、Viewの転がりはまだ速度があるので、速度によって次のViewの位置を計算したのだ.
では、このScrollerはVeiwを移動していませんが、何をしますか?これは補助移動で、私たちはいつでもgetCurrXとgetCurrYでViewの位置を得ることができて、それから..このVeiwをスクロールするにはScrollToを使用します.しかし注意しなければならないのは、ScrolToはViewの内容に対して、LinearLayoutであればScrollTo()、Linearlayoutの中のものはすべて移動します.それはTextViewです.ScrollTo()は、TextViewの中身が動いているだけなんですよね~、TextViewはそのまま動いていません.