0

Is it possible to setup different PageTransformers for different fragments in ViewPager?

I would like to use ZoomOutPageTransformer when the user swipes between (0, 1) and (n-1, n) fragments of ViewPager with n fragments and use the default transitions for all other cases.

What I tried:

Detect the current page with mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { ... }) and apply different transitions here. But, for example, if the user is on the first page - how to set ZoomOutPageTransformer only for the case when he will swipe to the left (0 page) and do it before animation is started?

Pang
  • 9,564
  • 146
  • 81
  • 122
Sergii
  • 1,521
  • 3
  • 24
  • 37

3 Answers3

1

I had a less similar requirement wherein I had applied Depth page transformer to all my pages by default and on tap of a button I changed it to Vertical page transformer and then back to Depth page. (A lil wierd but thats how it was)

I did the below:

  1. Applied viewPager.setPageTransformer(true, new DepthPageTransformer()); for all the pages.
  2. onClick I changed it to viewPager.setPageTransformer(true, new VerticalPageTransformer());. Now here's the catch in-order for this to function smoothly I had to use a handler in order to change the page a little later to ensure VerticalPager takes effect. I achieved this by calling viewPager.setCurrentPosition(viewPager.getCurrentItem() + 1)
  3. After this inside onPageChangeListener's onPageSelected method I changed it back to viewPager.setPageTransformer(true, new DepthPageTransformer()); again inside a handler to ensure it's done after my vertical animation is completed.

Note - I had also accessed ViewPager's scroller to achieve the above to define my own speed for the page change.

Let me know if this makes sense, since you need it to be done based on page numbers. If it does I will share my code. :)

Atul O Holic
  • 6,692
  • 4
  • 39
  • 74
  • Thanks a lot for your answer. My main problem here is to switch to different animation modes during scrolling to the different directions. So how to hardcode - if we are on the 1st page now - if the user scrolls to the right (pages 2+) - we should show default animation, but if to the left (back to the 0 page) - show ZoomOutPageTransformer one? – Sergii Dec 03 '14 at 18:46
1

This is quite old, but wish it's not too late for somebody

Step 1:

Create custom ViewPager which extends from ViewPager.

Step 2:

Determine which Fragment positions (ViewPager page integers) you need to have a unique PageTransformer for them. Then add these indices into a list within the custom ViewPager.

Step 3:

Override onPageScrolled(int position, float offset, int offsetPixels):

  • Check if the position is in your list of indices, if so, then you have to create a Custom PageTransformer object; and then utilize the ViewPager setPageTransformer() to change the page transformation.
  • For positions other than that, then you've to set the default PageTransformer (or you can also you another custom PageTransformer object if you wish.

Code

public class CustomViewPager extends ViewPager {

    public CustomViewPager(Context context) {
        super(context);
    }

    public CustomViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }


    PageTransformer mDepthPageTransformer = new PageTransformer() {
        private static final float MIN_SCALE = 0.75f;

        public void transformPage(@NonNull View view, float position) {
            int pageWidth = view.getWidth();

            if (position < -1) { // [-Infinity,-1)
                // This page is way off-screen to the left.
                view.setAlpha(0f);

            } else if (position <= 0) { // [-1,0]
                // Use the default slide transition when moving to the left page
                view.setAlpha(1f);
                view.setTranslationX(0f);
                view.setScaleX(1f);
                view.setScaleY(1f);

            } else if (position <= 1) { // (0,1]
                // Fade the page out.
                view.setAlpha(1 - position);

                // Counteract the default slide transition
                view.setTranslationX(pageWidth * -position);

                // Scale the page down (between MIN_SCALE and 1)
                float scaleFactor = MIN_SCALE
                        + (1 - MIN_SCALE) * (1 - Math.abs(position));
                view.setScaleX(scaleFactor);
                view.setScaleY(scaleFactor);

            } else { // (1,+Infinity]
                // This page is way off-screen to the right.
                view.setAlpha(0f);
            }
        }
    };

    PageTransformer mDefaultPageTransformer = new PageTransformer() {
        @Override
        public void transformPage(@NonNull View page, float position) {
        }
    };


    @Override
    protected void onPageScrolled(int position, float offset, int offsetPixels) {

        List<Integer> pos = new ArrayList<>();
        pos.add(0);
        pos.add(n - 1); // n is the no. of pages as in the question

        if (pos.contains(position)) {
            this.setPageTransformer(true, mDepthPageTransformer);

        } else {
            this.setPageTransformer(true, mDefaultPageTransformer);
        }

        super.onPageScrolled(position, offset, offsetPixels);
    }
}

Documentation

Note: mDepthPageTransformer used in my example is taken from the above mentioned documentation.

Zain
  • 37,492
  • 7
  • 60
  • 84
0

Inspite Of using mViewPager.setOnPageChangeListener , a single PageTransformer with different animations can help.

Have a look at first paragraph here ,

http://developer.android.com/training/animation/screen-slide.html#pagetransformer

MohK
  • 1,873
  • 1
  • 18
  • 29
  • Probably it is the same thing I'm doing now - applying different `PageTransformer` for different pages detecting which one is showing now? Or the idea is to detect current page inside custom `PageTransformer`? – Sergii Dec 01 '14 at 11:59