Android Scroller的理解

来源:互联网 发布:淘宝店铺上新提醒 编辑:程序博客网 时间:2024/05/21 22:59

要理解Android的原理,最好的方法是通过源码来分析。这次又来了,看看Scroller到底是什么?

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,这就是获得属性而已。

关键的两个方法如下:

/**     * 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的移动。


另一个是:

/**     * 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的位置,然后。。。使用ScrollTo来滚动这个Veiw.但是要注意的是,ScrollTo是针对View里面的内容的,如果是是LinearLayout.ScrollTo(),LinearLayout里面的东西全部移动,那如果是TextView.ScrollTo()呢,只是TextView里面的内容移动而已啦~,TextView还是原地不动的。

0 0