Android:Scroller动画?

我是Android开发的新手,我只想了解一下Scroller小部件(android.widget.Scroller)。它如何为视图制作动画?可以访问动画对象(如果存在)吗?如果是这样,怎么样?我已经阅读了源代码,但没有找到线索,或者我可能太新了? 我只是想在Scroller完成滚动之后做一些操作,比如说
m_scroller.getAnimation().setAnimationListener(...);
    
已邀请:
Scroller小部件实际上并没有为您完成大部分工作。它不会触发任何回调,它不会动画任何东西,它只响应各种方法调用。 那有什么用呢?嗯,它完成所有计算,例如为你而战,这很方便。所以你通常要做的就是创建一个Runnable,它反复询问Scroller,“我现在的卷轴位置应该是什么?我们是否完成了投掷?”然后你在Handler上重新发布runnable(通常在View上),直到完成一次。 这是我正在研究的片段中的一个例子:
private class Flinger implements Runnable {
    private final Scroller scroller;

    private int lastX = 0;

    Flinger() {
        scroller = new Scroller(getActivity());
    }

    void start(int initialVelocity) {
        int initialX = scrollingView.getScrollX();
        int maxX = Integer.MAX_VALUE; // or some appropriate max value in your code
        scroller.fling(initialX, 0, initialVelocity, 0, 0, maxX, 0, 10);
        Log.i(TAG, "starting fling at " + initialX + ", velocity is " + initialVelocity + "");

        lastX = initialX;
        getView().post(this);
    }

    public void run() {
        if (scroller.isFinished()) {
            Log.i(TAG, "scroller is finished, done with fling");
            return;
        }

        boolean more = scroller.computeScrollOffset();
        int x = scroller.getCurrX();
        int diff = lastX - x;
        if (diff != 0) {
            scrollingView.scrollBy(diff, 0);
            lastX = x;
        }

        if (more) {
            getView().post(this);
        }
    }

    boolean isFlinging() {
        return !scroller.isFinished();
    }

    void forceFinished() {
        if (!scroller.isFinished()) {
            scroller.forceFinished(true);
        }
    }
}
使用Scroller.startScroll的细节应该类似。     
比如Bill Phillips说,Scroller只是一个Android SDK类,有助于计算滚动位置。我在这里有一个完整的例子:
public class SimpleScrollableView extends TextView {
    private Scroller mScrollEventChecker;

    private int mLastFlingY;
    private float mLastY;
    private float mDeltaY;

    public SimpleScrollableView(Context context) {
        this(context, null, 0);
    }

    public SimpleScrollableView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public SimpleScrollableView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (mScrollEventChecker != null && !mScrollEventChecker.isFinished()) {
            return super.onTouchEvent(event);
        }

        final int action = event.getAction();

        switch (action) {
            case MotionEvent.ACTION_DOWN:
                mLastY = event.getY();
                return true;

            case MotionEvent.ACTION_MOVE:
                int movingDelta = (int) (event.getY() - mLastY);
                mDeltaY += movingDelta;
                offsetTopAndBottom(movingDelta);
                invalidate();
                return true;

            case MotionEvent.ACTION_UP:
                mScrollEventChecker = new Scroller(getContext());
                mScrollEventChecker.startScroll(0, 0, 0, (int) -mDeltaY, 1000);
                post(new Runnable() {
                    @Override
                    public void run() {
                        if (mScrollEventChecker.computeScrollOffset()) {
                            int curY = mScrollEventChecker.getCurrY();
                            int delta = curY - mLastFlingY;
                            offsetTopAndBottom(delta); // this is the method make this view move
                            invalidate();
                            mLastFlingY = curY;
                            post(this);
                        } else {
                            mLastFlingY = 0;
                            mDeltaY = 0;
                        }
                    }
                });
                return super.onTouchEvent(event);
        }

        return super.onTouchEvent(event);
    }
}
用户释放视图后,上面的演示自定义视图将滚动回原始位置。当用户释放视图时,调用startScroll()方法,我们可以知道每个消息帖的距离值。 完整的工作示例:Github存储库     
我们可以扩展
Scroller
类,然后拦截相应的动画启动方法来标记已启动的,在computeScrollOffset()返回false后表示动画结束的值,我们通过监听器通知调用者:
public class ScrollerImpl extends Scroller {
    ...Constructor...

    private boolean mIsStarted;
    private OnFinishListener mOnFinishListener;

    @Override
    public boolean computeScrollOffset() {
        boolean result = super.computeScrollOffset();
        if (!result && mIsStarted) {
            try { // Don't let any exception impact the scroll animation.
                mOnFinishListener.onFinish();
            } catch (Exception e) {}
            mIsStarted = false;
        }
        return result;
    }

    @Override
    public void startScroll(int startX, int startY, int dx, int dy) {
        super.startScroll(startX, startY, dx, dy);
        mIsStarted = true;
    }

    @Override
    public void startScroll(int startX, int startY, int dx, int dy, int duration) {
        super.startScroll(startX, startY, dx, dy, duration);
        mIsStarted = true;
    }

    @Override
    public void fling(int startX, int startY, int velocityX, int velocityY, int minX, int maxX, int minY, int maxY) {
        super.fling(startX, startY, velocityX, velocityY, minX, maxX, minY, maxY);
        mIsStarted = true;
    }

    public void setOnFinishListener(OnFinishListener onFinishListener) {
        mOnFinishListener = onFinishListener;
    }

    public static interface OnFinishListener {
        void onFinish();
    }
}
    
上面的答案很棒。 Scroller #startScroll(...)确实以相同的方式工作。 例如,自定义滚动TextView的源代码: http://bear-polka.blogspot.com/2009/01/scrolltextview-scrolling-textview-for.html 使用TextView#setScroller(Scroller)在TextView上设置Scroller。 SDK的TextView源代码: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.2_r1.1/android/widget/TextView.java#TextView.0mScroller 显示TextView#setScroller(Scroller)设置一个类字段,该字段用于调用Scroller#scrollTo(int,int,int,int)的bringPointIntoView(int)等情况。 bringPointIntoView()调整mScrollX和mScrollY(带有一些SDK碎片代码),然后调用invalidate()。所有这一切的要点是mScrollX和mScrollY在onPreDraw(...)等方法中用于影响视图绘制内容的位置。     

要回复问题请先登录注册