Matt Accola Matt Accola - 2 months ago 36
Android Question

FragmentTransaction animation to slide in over top

I am trying to achieve the following effect using FragmentTransaction.setCustomAnimations.


  1. Fragment A is showing

  2. Replace Fragment A with Fragment B. Fragment A should remain visible during the replacement. Fragment B should slide in from the right. Fragment B should slide in OVER THE TOP of Fragment A.



I have no problem getting the slide in animation setup. My problem is that I cannot figure out how to make Fragment A stay where it is and be UNDER Fragment B while the slide in animation is running. No matter what I do it seems that Fragment A is on top.

How can I achieve this?

Here is the FragmentTransaction code:

FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.setCustomAnimations(R.anim.slide_in_right, R.anim.nothing, R.anim.nothing,
R.anim.slide_out_right);
ft.replace(R.id.fragment_content, fragment, name);
ft.addToBackStack(name);
ft.commit();


As you can see I have defined an animation R.anim.nothing for the "out" animation because I actually don't want Fragment A to do anything other than just stay where it is during the transaction.

Here are the animation resources:

slide_in_right.xml

<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="@android:integer/config_mediumAnimTime"
android:fromXDelta="100%p"
android:toXDelta="0"
android:zAdjustment="top" />


nothing.xml

<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="@android:integer/config_mediumAnimTime"
android:fromAlpha="1.0"
android:toAlpha="1.0"
android:zAdjustment="bottom" />

Answer

I found a solution which works for me. I ended up using a ViewPager with a FragmentStatePagerAdapter. The ViewPager provides the swiping behavior and the FragmentStatePagerAdapter swaps in the fragments. The final trick to achieve the effect of having one page visible "under" the incoming page is to use a PageTransformer. The PageTransformer overrides the ViewPager's default transition between pages. Here is an example PageTransformer that achieves the effect with translation and a small amount of scaling on the left-hand side page.

public class ScalePageTransformer implements PageTransformer {
    private static final float SCALE_FACTOR = 0.95f;

    private final ViewPager mViewPager;

    public ScalePageTransformer(ViewPager viewPager) {
            this.mViewPager = viewPager;
    }

    @SuppressLint("NewApi")
    @Override
    public void transformPage(View page, float position) {
        if (position <= 0) {
            // apply zoom effect and offset translation only for pages to
            // the left
            final float transformValue = Math.abs(Math.abs(position) - 1) * (1.0f - SCALE_FACTOR) + SCALE_FACTOR;
            int pageWidth = mViewPager.getWidth();
            final float translateValue = position * -pageWidth;
            page.setScaleX(transformValue);
            page.setScaleY(transformValue);
            if (translateValue > -pageWidth) {
                page.setTranslationX(translateValue);
            } else {
                page.setTranslationX(0);
            }
        }
    }

}
Comments