javaandroidandroid-viewpagershadowandroid-pagetransformer

ViewPager.PageTransformer with a drop shadow


I have a stack of fragments in a ViewPager, with a custom PageTransformer defined as below.

mPager.setPageTransformer(true, new ViewPager.PageTransformer() {
    @Override
    public void transformPage(View page, float position) {
        page.setTranslationX(page.getWidth() * -position);
    }
}); 

How can I draw a shadow for the leaving fragment ? Long story short I'm looking for something as in Play Book, no curl effects needed, just the shadow of the element on the top of the stack, preferably API 18 compliant

Thank you


Solution

  • I had doubts about setPageMargin because it works only if the incoming view has an alpha transparency. I mean, it seems that the margin has a wrong elevation and it stands below the incoming view, but maybe I've found a compromise

    enter image description here

    This is the code in the activity for the margin and the custom PageTransformer

        int margin = getResources().getDisplayMetrics().widthPixels / 15;
        mPager = (ViewPager) findViewById(R.id.pager);
    
        mPager.setPageMargin(margin);
        mPager.setPageMarginDrawable(R.drawable.shadow);
        mPager.setPageTransformer(true, new StackTransformer());
    

    where the drawable is defined as

        <shape xmlns:android="http://schemas.android.com/apk/res/android" 
           android:shape="rectangle" >
            <gradient
                android:angle="360"
                android:endColor="#00000000"
                android:startColor="#aa000000"
                android:type="linear" />
        </shape>
    

    At last the transformPage method of the PageTransformer, where I played with position and alpha to find an acceptable effect

    @Override
    public void transformPage(View view, float position) {
        int pageWidth = view.getWidth();
        if (position < -1) {
            view.setAlpha(0);
        } else if (position <= 0) { 
            view.setAlpha(1);
            view.setTranslationX(0);
        } else if (position <= 1) { 
            view.setAlpha(1-position/2); // divide by 2 is the trick
            view.setTranslationX(pageWidth * -position);
        } else { 
            view.setAlpha(0);
        }
    }
    

    The resulting effect is what you see in the gif above, but I'm sure that out there, there is a better way to achieve this effect