Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to achieve a ViewPager with previous and next page shown and bigger focused page

I'm trying to create something that will display my pages on a viewpager for it to have nice feel and design and I checked out this link which somehow helps and also follow this link on how I can implement it but I ended up with some issues. First is that it won't really work or look that good for devices that runs below API11 (API8 is my target). and Second is that I can't manage to make the focused page to be bigger than the next and previous page. I wanted it look something like this for the sake of design:

enter image description here

Hope someone can help me on this or any other way to achieve this.

like image 982
KaHeL Avatar asked Aug 22 '14 04:08

KaHeL


People also ask

How do you make a ViewPager only resume selected fragment?

1 Answer. Show activity on this post. You cannot do that, the viewpager requires at least one fragment to the left and one to the right. I suggest you move the onResume() logic to a separate method and call it when the fragment becomes visible.

How many methods does the PageTransformer of a ViewPager expose?

PageTransformer is the interface that we have to implement and then supply it to the view pager. According to Android's official documentation, it has only one single method transform page().

How the ViewPager is implemented?

Layout manager that allows the user to flip left and right through pages of data. You supply an implementation of a PagerAdapter to generate the pages that the view shows. ViewPager is most often used in conjunction with android.


1 Answers

Read this first. Then apply your own PageTransformer implementation. Something like this:

public class DepthPageTransformer implements ViewPager.PageTransformer {
    private static final float MIN_SCALE = 0.5f;
    private static final float MAX_SCALE = 0.8f;
    private static final float MIN_FADE = 0.2f;

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

        if (position < -1) {
            view.setAlpha(MIN_FADE);
        } else if (position < 0) {
            view.setAlpha(1 + position * (1 - MIN_FADE));
            view.setTranslationX(-pageWidth * MAX_SCALE * position);
            ViewCompat.setTranslationZ(view, position);
            float scaleFactor = MIN_SCALE
                    + (MAX_SCALE - MIN_SCALE) * (1 - Math.abs(position));
            view.setScaleX(scaleFactor);
            view.setScaleY(scaleFactor);
        } else if (position == 0) {
            view.setAlpha(1);
            view.setTranslationX(0);
            view.setScaleX(MAX_SCALE);
            ViewCompat.setTranslationZ(view, 0);
            view.setScaleY(MAX_SCALE);
        } else if (position <= 1) {
            ViewCompat.setTranslationZ(view, -position);
            view.setAlpha(1 - position * (1 - MIN_FADE));
            view.setTranslationX(pageWidth * MAX_SCALE * -position);

            float scaleFactor = MIN_SCALE
                    + (MAX_SCALE - MIN_SCALE) * (1 - Math.abs(position));
            view.setScaleX(scaleFactor);
            view.setScaleY(scaleFactor);
        } else {
            view.setAlpha(MIN_FADE);
        }
    }
}

You will also need to control the child drawing order to set the current selected View on top (only needed, if your views overlay each other):

public class MyPager extends ViewPager {
    public MyPager(Context context) {
        this(context, null);
    }

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

    @Override
    protected int getChildDrawingOrder(int childCount, int i) {
        if(i == childCount - 1) {
            return getCurrentItem();
        } else {
            return i >= getCurrentItem()? i + 1 : i;
        }
    }
}

Set ViewPager.setOffscreenPageLimit to 2 or even more, if you have more visible pages on screen.

Here is the result:

Result animation

like image 171
artkoenig Avatar answered Oct 04 '22 16:10

artkoenig