Velocity View Pager setCurrentItem无法正常工作

时间:2014-08-29 22:24:14

标签: android android-viewpager

我正在使用VelocityViewPager found in this post来实现可移动的ViewPager。我试图通过在VelocityViewPager(1970年代)中间显示一个元素来设置视图寻呼机进行初始化。所以在我的片段的onViewCreated()中我做了:

velocityViewPager.setCurrentItem(69);

用户建议执行以下操作以在post的评论中解决此问题:

private void trackMotion(float distX) {
    final int width = getWidth();
    final int widthWithMargin = width + this.getPageMargin();
    float scrollOffset = getScrollX() - (this.getCurrentItem() * widthWithMargin);
    float scrollX = getScrollX() - distX - scrollOffset;
    ........
}

然而,当我尝试这个时,它不起作用,我会被看到ViewPager的元素68,69和70,因为scrollX会被卡住,因为偏移会锁定" scrollX到范围。

我注意到的问题是当scrollX真正应该是表示位置69的值时,它被初始化为0.我尝试在XML中手动设置scrollX,在Java代码中设置scrollX,并进行各种偏移计算无济于事。

1 个答案:

答案 0 :(得分:1)

这就是我最终为一个可观的观点所做的事情。这肯定更痛苦(我需要大量的试验和错误)而不仅仅是从视图寻呼机扩展,但它给了我想要的东西。您必须找到一种方法来使用View的scrollX来确定要捕捉的项目以及到达视图结束或开始时要执行的操作。

public class FlingableScroller extends View implements GestureDetector.OnGestureListener {

    public FlingableScroller(Context context, AttributeSet attrs) {
        super(context, attrs);
        mGestureDetector = new GestureDetector(context, this);
        mScroller = new OverScroller(context);
        //This is how you "set current item" You will have to calculate INITIAL_SCROLL_X yourself
        setScrollX(INITIAL_SCROLL_X);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        animateFlingIfApplicable();
    }

    private void animateFlingIfApplicable() {
        //We have a fling only if computeScrollOffset is true.
        if (mScroller.computeScrollOffset()) {
            //Flinging passed the start point so continue the fling at the end
            if (mScroller.getFinalX() == 0) {
                int velocity = getFlingVelocity();
                mScroller.forceFinished(true);
                mScroller.fling(MAXIMUM_SCROLL_X, 0, velocity / FRICTION_COEFFICIENT, 0, 0, MAXIMUM_SCROLL_X, 0, 0);
                //Flinging passed the end point so continue the fling at the start
            } else if (mScroller.getFinalX() == MAXIMUM_SCROLL_X) {
                int velocity = getFlingVelocity();
                mScroller.forceFinished(true);
                mScroller.fling(0, 0, velocity / FRICTION_COEFFICIENT, 0, 0, MAXIMUM_SCROLL_X, 0, 0);
            } else if (mScroller.getFinalX() == getScrollX() || mScroller.getCurrVelocity() == 0) {
                snapToItem();
                mScroller.forceFinished(true);
            } else {
                scrollTo(mScroller.getCurrX(), 0);
            }
        }

        invalidate();
    }

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
        //This logic handles the case when you scroll pass the beginning or the end of the scroller
        if (getScrollX() > MAXIMUM_SCROLL_X) {
            scrollTo(0, 0);
        } else if (getScrollX() >= 0) {
            scrollBy(distance, 0);
        } else {
            scrollTo(MAXIMUM_SCROLL_X, 0);
        }
        invalidate();
        return true;
    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        //This is to prevent low velocity "flings"
        if (Math.abs(velocityX) < 400 * SCREEN_DENSITY) {
            return false;
        }

        mScroller.forceFinished(true);
        //Define friction_coefficient to a value that gives you desirable flinging.
        mScroller.fling(getScrollX(), getScrollY(), (int) -velocityX / FRICTION_COEFFICIENT, 0, 0, MAXIMUM_SCROLL_X, 0, 0);
        invalidate();
        return true;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mScroller.forceFinished(true);
                break;
            case MotionEvent.ACTION_UP:
                snapToItem();
                invalidate();
                break;
    }
        return mGestureDetector.onTouchEvent(event);
    }

    private void snapToItem() {
        //The the user lifts up their finger from a scroll or when a fling finishes determine what item to snap to. See the ViewPager source code to emulate the "fake drag"
        int scrollByValue = getScrollX() / SOME_VALUE
        scrollTo(scrollByValue, 0);
    }
}