【问题标题】:Velocity View Pager setCurrentItem not working速度视图寻呼机 setCurrentItem 不工作
【发布时间】:2014-08-29 22:24:13
【问题描述】:

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

velocityViewPager.setCurrentItem(69);

一位用户建议在post 的 cmets 中执行以下操作来解决此问题:

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 被初始化为 0,而它实际上应该是一个表示位置 69 的值。我尝试在 XML 中手动设置 scrollX,在 Java 代码中设置 scrollX,并进行各种偏移计算,但无济于事。

【问题讨论】:

    标签: android android-viewpager


    【解决方案1】:

    这就是我最终为 flingable 视图所做的事情。这肯定比仅仅从视图寻呼机扩展更痛苦(它需要我进行大量的试验和错误),但它给了我想要的东西。您必须想办法使用 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);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-06-05
      • 2014-03-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-22
      相关资源
      最近更新 更多