Android Viewpager bounce to half a page
Asked Answered
L

3

8

So what i am trying to achieve is user would open to first page of the view pager, and the view pager would bounce to half of the second page and bounce back to the fist page indicating that there are more pages to scroll to. I was wondering on how i could implement this?

Libava answered 24/8, 2014 at 20:12 Comment(0)
V
21

You can use fakeDragBy method to achieve this effect:

viewPager.beginFakeDrag();
viewPager.fakeDragBy(offset); //offset in pixels. 
viewPager.endFakeDrag();

EDIT:

I have made method for this:

private int animFactor;
private ValueAnimator animator = new ValueAnimator();

private void animateViewPager(final ViewPager pager, final int offset, final int delay) {
    if (!animator.isRunning()) {
        animator.removeAllUpdateListeners();
        animator.removeAllListeners();
        //Set animation
        animator.setIntValues(0, -offset);
        animator.setDuration(delay);
        animator.setRepeatCount(1);
        animator.setRepeatMode(ValueAnimator.RESTART);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            public void onAnimationUpdate(ValueAnimator animation) {
                Integer value = animFactor * (Integer) animation.getAnimatedValue();
                if (!pager.isFakeDragging()) {
                    pager.beginFakeDrag();
                }
                pager.fakeDragBy(value);
            }
        });
        animator.addListener(new AnimatorListenerAdapter() {

            @Override
            public void onAnimationStart(Animator animation) {
                animFactor = 1;
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                pager.endFakeDrag();
            }

            @Override
            public void onAnimationRepeat(Animator animation) {
                animFactor = -1;
            }
        });
        animator.start();
    }
}

Example of usage:

animateViewPager(pager, 10, 1000);

Edit2: ValueAnimator is class for Api level 11. Also set pager adapter before calling this method.

Vance answered 24/8, 2014 at 20:39 Comment(10)
I have tested this and it just causes crash, saying beginFakeDrag not called, when i do the offset it doesn't move the viewpager at all even when calling beginFakeDrag and endFakeDragLibava
Ok, I have fixed and tested code. Try It now, see code above.Vance
This leads to index out of bound stating that index is 0 and size is 0. Should the view pager be at specific page? Currently the view pager consists of 5 pages.Libava
It's crashing for me too. Getting index out of bound. I'm calling the method onCreate.Mockheroic
What exception? Have you set pager adapter before calling this method? ValueAnimator is api level 11.Vance
I am also getting the crash "Invalid index 0, size is 0". for testing purposes, I can avoid the crash by calling the method inside a click listener (and confirm that the animation does work), but I ideally I'd want the method to be called automatically when the view is created. it crashes when I call it in onViewCreated, any ideas?Forebrain
also it crashes on rotate while the animation is activeForebrain
for future reference, the code by Yuraj does work, but I had to use try/catches to avoid the above crashes. in addition to that, animator.setRepeatCount(1); should be (2), not (1).Forebrain
Replace pager.fakeDragBy(value); with int xOffset = value - mFakeDragOffsetTotal; pager.fakeDragBy(xOffset); mFakeDragOffsetTotal += xOffset; where mfakeDragOffsetTotal is zero on animation start. This will ensure max offset applied to drag.Draughtsman
But there is a unwanted scenario here. Lets we have 2 view pager and second one is visible 20-30%. when bounce effect and view moves to left side, the second page which was shown 20% too moves left , which is fine but even if it moves left side it displays 20% PORTION ONLY. The reason here is that bounce effect is on VIEW PAGER , not on the pages inside it. any solution for it?Increate
Q
1

Adding a note to @Yuraj's answer. Call the method in onWindowFocusChanged when hasFocus==true as follows to avoid indexOutOfBoundsException:

@Override
public void onWindowFocusChanged(boolean hasFocus) 
{
    super.onWindowFocusChanged(hasFocus);

    if(hasFocus)
    {
        Handler handler = new Handler();

        final Runnable r = new Runnable() 
        {
            public void run() 
            {
                if(mViewPager.getCurrentItem() == 0)
                {
                    Context context = Activity_main.this;
                    String filename="Init";
                    SharedPreferences stats;
                    stats = context.getSharedPreferences(filename, 0); 
                    int appOpen = stats.getInt("appOpen", 0);

                    if(appOpen <= 5)
                    {
                        animateViewPager(mViewPager, 10, 300);

                        appOpen += 1;
                        SharedPreferences.Editor editor = stats.edit();
                        editor.putInt("appOpen", appOpen);
                        editor.commit();
                    }
                }
            }
        };

        handler.postDelayed(r, WAIT_VIEWPAGER_NUDGE);

    }
}
Queen answered 10/6, 2016 at 2:23 Comment(0)
P
0

Thank you Yuvraj! It worked with a simple modification. If anybody is getting "Invalid index 0, size is 0" error, here's a simple fix for it. If you call animateViewPager() method in onCreate() you might get this error, "Invalid index 0, size is 0". I believe viewpager.beginFakeDrag(); is being called before viewPager items / childs are initialized. So, call animateViewPager() with a delay like so:

new Handler().postDelayed(() -> animateViewPager(viewPager, 10, 1000), 500);

500 is the delay in milisecond

Pioneer answered 22/6, 2022 at 3:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.