Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/211.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android:滚动动画?_Android_Animation_Scroll_Scroller - Fatal编程技术网

Android:滚动动画?

Android:滚动动画?,android,animation,scroll,scroller,Android,Animation,Scroll,Scroller,我是Android开发的新手,我只想了解一下Scroller小部件(Android.widget.Scroller)。它如何设置视图的动画?是否可以访问动画对象(如果存在)?如果是,怎么做?我读过源代码,但找不到任何线索,或者我太新了 我只是想在滚动器完成滚动后做一些操作,比如 m_scroller.getAnimation().setAnimationListener(...); Scroller小部件实际上并没有为您做很多工作。它不触发任何回调,也不设置任何动画,它只响应各种方法调用 那有

我是Android开发的新手,我只想了解一下Scroller小部件(Android.widget.Scroller)。它如何设置视图的动画?是否可以访问动画对象(如果存在)?如果是,怎么做?我读过源代码,但找不到任何线索,或者我太新了

我只是想在滚动器完成滚动后做一些操作,比如

m_scroller.getAnimation().setAnimationListener(...);

Scroller小部件实际上并没有为您做很多工作。它不触发任何回调,也不设置任何动画,它只响应各种方法调用

那有什么好处呢?好吧,它为你做了所有的计算,比如说一次放纵,这很方便。因此,您通常要做的是创建一个Runnable,反复询问滚动条,“我的滚动位置现在应该是什么?我们是否完成了投掷?”然后将该Runnable重新发布到处理程序上(通常在视图上),直到投掷完成

下面是我正在研究的一个片段的示例:

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的详细信息应该类似。

上面的回答很好。Scroller#startScroll(…)的工作方式确实相同

例如,自定义滚动文本视图的源位于:

使用TextView#setScroller(滚动条)在TextView上设置滚动条

SDK的TextView的源代码位于:

显示TextView#setScroller(Scroller)设置一个类字段,该字段在调用Scroller#scrollTo(int,int,int,int)的情况下使用


bringPointIntoView()调整mScrollX和mScrollY(使用一些SDK碎片代码),然后调用invalidate()。所有这一切的要点是,mScrollX和mScrollY在onPreDraw(…)等方法中被用来影响视图中绘制内容的位置。

我们可以扩展
滚动器
类,然后在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();
    }
}

正如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()方法,我们可以知道每条消息的距离值应该是多少


完整的工作示例:

我明白了。因此,您为滚动条实现了一种侦听器线程。美好的谢谢!:)您的
isFlinging()方法不应该返回
!scroller.isFinished()
?要么将其重命名为
isFinished()
。很好的例子:)是的,它应该。固定的。谢谢希望有人能给我解释一下。在我问这个问题差不多两年后,我想你也可以创建一个子类,它接受一个委托,并定期调用该委托上的某些方法,即onScrollFinished()或onOverscroll(),在我看来,这比一直轮询滚动条要好@比尔菲利普斯:不过你在这件事上确实帮了我的忙。:)前面的实现使用一个线程来轮询滚动器的滚动位置。在扩展Scroller的实现中,如何从视图中轮询ScrollerImpl以获得滚动位置的更改?对不起,我不太清楚您的问题,您想知道如何使用
ScrollerImpl
?@carignan.boy在这种情况下您不轮询。您要做的是设置ScrollerImpl OnFinishListener,然后等待调用onFinish()方法。这样做比投票要好得多;这正是我在接受答案的评论中的意思。