onemach
onemach

Reputation: 4325

viewpager automatically scroll too fast

I have a ViewPager which has 4 pages and I want it scroll automatically.

What I am doing is viewPager.setCurrentItem(index); bound with a TimerTask where index is a precomputed integer.

The logic works fine but when it scroll (triggered by setCurrentImte) the animation is too fast.

How can I control the scroll speed of it? Please note I am talking about the scrolling animation speed, instead of the interval of 2 successive scroll.

Upvotes: 1

Views: 4334

Answers (4)

Rubin
Rubin

Reputation: 212

I have the same requirement on an app i am developing and my solution was this.

    Observable.range(1, vpAdapter.getCount() - 1)
            .concatMap(i-> Observable.just(i).delay(5000, TimeUnit.MILLISECONDS))
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(integer -> {
                currentAutoPage = integer;

                binding.vpTour.beginFakeDrag();
                lastFakeDrag = 0;
                ValueAnimator va = ValueAnimator.ofInt(0, binding.vpTour.getWidth());
                va.setDuration(1000);
                va.addUpdateListener(animation -> {
                    if (binding.vpTour.isFakeDragging()) {
                        int animProgress = (Integer) animation.getAnimatedValue();
                        binding.vpTour.fakeDragBy(lastFakeDrag - animProgress);
                        lastFakeDrag = animProgress;
                    }
                });
                va.addListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        super.onAnimationEnd(animation);
                        if (binding.vpTour.isFakeDragging()) {
                            binding.vpTour.endFakeDrag();
                        }
                    }
                });
                va.start();
            }, Throwable::printStackTrace, () -> {
                if (autoPageChangeDisposable != null && !autoPageChangeDisposable.isDisposed()) {
                    autoPageChangeDisposable.dispose();
                }
            });

In case you also want to stop the automatic swiping when user manually changes the page than just get the disposable from this code that i wrote, like this : "Disposable autoPageChangeDisposable = Observable.range(1, vpAdapter...." and than register and OnPageChangedListener and do this :

        vpTour.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
            @Override
            public void onPageSelected(int position) {
                if (position != currentAutoPage) {
                    if (autoPageChangeDisposable != null && !autoPageChangeDisposable.isDisposed()) {
                        autoPageChangeDisposable.dispose();
                    }
                }
            }
        });

Upvotes: 0

user1113374
user1113374

Reputation: 1

Why not try something like this? Use a value animator to animate the scroll values, then update the positioning so the fragment loading is correctly handled. Works fine for me :).

if(pager != null){
        ValueAnimator scrollAnimator = ValueAnimator.ofInt(pager.getScrollX(), pager.getScrollX()+2560);
        final int virtualPage = pager.getCurrentItem();
        scrollAnimator.setDuration(1000);
        scrollAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                pager.setScrollX((Integer)animation.getAnimatedValue());
            }
        });
        scrollAnimator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                pager.setCurrentVirtualItem(virtualPage, false);
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
        scrollAnimator.start();
    } 

Upvotes: 0

Chris
Chris

Reputation: 343

Why not use a ViewFlipper instead? A ViewFlipper has built in functionality to handle auto-scrolling between views, which means you can dump the timer. Also, it implements ViewAnimator which gives you full control over the animations. It is relatively simple to create custom animations, and you have control over the time it takes to animate. A simple tutorial for a slide animation can be found here. Take note of the duration attribute of the animation xml files.

Upvotes: 2

sandrstar
sandrstar

Reputation: 12643

Looks like ViewPager doesn't provide such an API. I would suggest to do any of the following:

  • Take VieWPager code (it's under Your android sdk extras folder) and twek it the way you need (e.g. add necessary API). Now it seems to use internal constant (MAX_SETTLE_DURATION);
  • Intercept touches by yourself and call fakeDragBy() (not sure if its what You're looking for);

Upvotes: 0

Related Questions