Scroller入门

常用方法

        构造函数,源码如下:
    public Scroller(Context context, Interpolator interpolator, boolean flywheel) {
        mFinished = true;
        if (interpolator == null) {
            mInterpolator = new ViscousFluidInterpolator();
        } else {
            mInterpolator = interpolator;
        }
        mPpi = context.getResources().getDisplayMetrics().density * 160.0f;
        mDeceleration = computeDeceleration(ViewConfiguration.getScrollFriction());
        mFlywheel = flywheel;

        mPhysicalCoeff = computeDeceleration(0.84f); // look and feel tuning
    }
无非是将一些参数进行赋值而已。略。
        startScroll():开始滚动,但也是一堆的赋值。如下:
    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;
    }
        主要看最后一个全局变量,指的是duration的倒数。用该数乘以已经滚动过的时候,就可以得到当前的滚动比例。并且将mMode设置为SCROLL_MODE。
        fling():滑动。手指脱离屏幕后,view会依旧滚动一段距离,这个滚动过程被称为fling。前两个参数为fling的起始位置,第三四个为fling时x,y轴的速度,第五六个为在x轴上最小滚动距离与最大滚动距离,第七八个为在y轴上的最小滚动距离与最大滚动距离。源码如下:
    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);
    }
        首先看if判断。首先假定if判断是成立的,根据距离比,将fling时的速度进行分解,然后将分解得到的x,y轴上的速度分别添加上fling参数中的x,y轴的速度上。因此,mFlywheel的作用就很简单:控件在fling时是否考虑当前的速度,如果不考虑,那么fling的初速度只是fling()中设置的值,否则就是fling时的速度+fling()中设置的值。
        if判断下面,首先将速度合成,然后计算x,y轴上的速度系数及总的移动距离(getSplineDistance()的作用,但看不懂),最后根据x,y轴上的速度系数计算出x,y轴上的移动距离。
        也就是说该方法的作用与startScroll()一样,只不过fling()中的好多值都是需要进行计算的。
        computeScrollOffset():计算当前的滚动的偏移量。返回值表示本次移动是否已经结束。如下
    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;
    }
        在该方法中,只是为mCurrX,mCurrY进行了赋值,因此,如果在该方法返回true的情况下,需要调用Scroller#getCurrX(),Scroller#getCurrY()获取新的数值。
        在SCROLL_MODE下,首先计算出滚动的持续时间,然后通过插值器计算出一个新的滚动因子(即当前的滚动比例)。从这里也可以看出插值器的作用:将一个线性的因子改变,并使用改变后的值去计算别的数值,这样得到的数据就可以达到各种效果,如:先加速后减速等。
        在FLING_MODE下,首先也是计算速度因子、距离因子(计算看不懂),然后也是为mCurrX,mCurrY设置数据。

示例

    public void startScroll() {
        mScroller.startScroll(getLeft(), getTop(), 500, 500);
        invalidate();
    }

    @Override
    public void computeScroll() {
        if (mScroller.computeScrollOffset()) {
            int currX = mScroller.getCurrX();
            int currY = mScroller.getCurrY();
            ((ViewGroup)getParent()).scrollTo(-currX, -currY);
            invalidate();
        }
    }




你可能感兴趣的:(Scroller入门)