Android小总结:Scroller

来源:互联网 发布:虚拟展馆什么软件 编辑:程序博客网 时间:2024/06/05 21:14

如果说scrollTo()和scrollBy()方法是一栋房子,那么Scroller类可以看成房子的装潢,Scroller可以让我们的房子更加漂亮。

在使用scrollTo()和scrollBy()的方法时,被移动的View是瞬间到达目的地,不能看到View是怎么移动到目的地的,那么就可以通过Scroller类来进行修饰。

Scroller类用于跟踪控件滑动的轨迹,此类不会移动控件,需要你在View的回调函数computerScroll()中使用Scroller对象获取滑动的数据来控制View。

Scroller类可以让我们看到View的移动过程,Scroller类有两个重要的方法computeScrollOffset()和startScroll()。


computeScrollOffset():

这个方法如果返回true,说明动画没有结束,那么动画结束,就会返回false,说明到达了目的地,滚动完成。

 /**     * Call this when you want to know the new location.  If it returns true,     * the animation is not yet finished.     * 想知道新位置时调用此方法,如果返回为true,说明动画还没有结束     */    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;    }

startScroll()方法有两个,一个是带动画时间参数的,一个不带。

只有调用Scroller的startScroll()方法时,动画才会开始执行。

/**     * Start scrolling by providing a starting point and the distance to travel.     * The scroll will use the default value of 250 milliseconds for the     * duration.     * 通过一个起始点和移动距离开始滚动。     * 滚动时间默认为250毫秒     *     * @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.     *               移动的垂直距离。正数则内容向上滚动     */    public void startScroll(int startX, int startY, int dx, int dy) {        startScroll(startX, startY, dx, dy, DEFAULT_DURATION);    }

/**     * 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;    }


有了computeScrollOffset()和startScroll()方法,那么接下来自定义View时重写View的computeScroll()方法就可以完成View的滚动。

自定义View,重写此方法:
/**     * Called by a parent to request that a child update its values for mScrollX     * and mScrollY if necessary. This will typically be done if the child is     * animating a scroll using a {@link android.widget.Scroller Scroller}     * object.     * 有必要时,子视图使用Scroller动画滚动,由父视图调用子视图更新mScrollX和mScrollY值     */    public void computeScroll() {    }


小例子:

自定义一个TextView,然后TextView中的文字移动一段距离。

Activity类:

package com.zwc.admin.scrollerdemo;import android.support.v7.app.ActionBarActivity;import android.os.Bundle;import android.view.View;import android.widget.Button;public class MainActivity extends ActionBarActivity {    private static final String TAG = "MainActivity";    private MyTextView mContentTextView;    private Button mScrollerButton;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        //init views        mContentTextView = (MyTextView) findViewById(R.id.tv_txt);        mScrollerButton = (Button) findViewById(R.id.btn_scroller);        mScrollerButton.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                mContentTextView.beginScroll(0, 0, 200, 200, 5000);            }        });    }}

自定义TextView类:


package com.zwc.admin.scrollerdemo;import android.content.Context;import android.util.AttributeSet;import android.widget.Scroller;import android.widget.TextView;/** * TODO: document your custom view class. */public class MyTextView extends TextView {    private static final String TAG = "MyTextView";    private Scroller mScroller;    public MyTextView(Context context) {        super(context);        init(context);    }    public MyTextView(Context context, AttributeSet attrs) {        super(context, attrs);        init(context);    }    public void init(Context context) {        mScroller = new Scroller(context);    }    @Override    public void computeScroll() {        if (mScroller.computeScrollOffset()) {            scrollTo(-mScroller.getCurrX(), -mScroller.getCurrY());            postInvalidate();        }        super.computeScroll();    }    /**     * @param startX 起始位置     * @param startY 起始位置     * @param dx 移动距离     * @param dy 移动距离     * @param duration 动画执行时间     */    public void beginScroll(int startX, int startY, int dx, int dy, int duration) {        mScroller.startScroll(startX,  startY,  dx,  dy,  duration);        invalidate();    }}


xml文件:


<RelativeLayout    xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical">    <com.zwc.admin.scrollerdemo.MyTextView        xmlns:android="http://schemas.android.com/apk/res/android"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:id="@+id/tv_txt"        android:background="#FF4040"        android:text="我会移动"/>    <Button        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:id="@+id/btn_scroller"        android:text="点我滚动文字"       android:layout_centerInParent="true"/></RelativeLayout>




0 0
原创粉丝点击