Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change z-order of Fragments during ongoing FragmentTransaction

Is there a way how to change the z-order in which are fragments displayed during an ongoing FragmentTransaction? I've an animation where both fragments overlaps each other and I would like to have the fragment which slides from the right (the second fragment) displayed under the other one which slides to the left. Right now they are displayed in opposite order during the transaction.

Here is code of one of my animations:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
 android:duration="400"
 android:zAdjustment="bottom">
<scale android:toXScale="1"
    android:fromXScale="0.9"
    android:pivotX="50%p"
    android:pivotY="50%p"
    android:toYScale="1"
    android:startOffset="300"
    android:fromYScale="0.9"/>
<translate android:fromXDelta="50%p"
    android:interpolator="@android:interpolator/overshoot"
    android:toXDelta="0"/>

</set>

And here is the code of the transaction

FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.show(fragmentToShow).hide(fragmentToHide).commit();

I would like to have the fragmentToHide to appear under the fragmentToShow. I've tried to tackle with the android:zAdjustment property, but since it apparently works only for window animations it just haven't worked for me.

like image 671
simekadam Avatar asked Feb 04 '14 18:02

simekadam


People also ask

How do you move from one fragment to another in Kotlin?

Step 1 − Create a new project in Android Studio, go to File ⇉ New Project and fill all required details to create a new project. Step 2 − Add the following code to res/layout/activity_main. xml. Step 3 − Create two FragmentActivity and add the codes which are given below.

How do you animate fragment transitions?

At a high level, here's how to make a fragment transition with shared elements: Assign a unique transition name to each shared element view. Add shared element views and transition names to the FragmentTransaction . Set a shared element transition animation.

What is the process of starting a new fragment?

The android:name attribute specifies the class name of the Fragment to instantiate. When the activity's layout is inflated, the specified fragment is instantiated, onInflate() is called on the newly instantiated fragment, and a FragmentTransaction is created to add the fragment to the FragmentManager .


1 Answers

I also had this problem and the only workaround I have been able to find is to place another FrameLayout directly under the one that holds the current fragment. Then I transition my new fragment into the alternate FrameLayout (which has a higher z-ordering than the FrameLayout below it) and remove the old fragment from the original FrameLayout in the same transaction. Something like this:

<FrameLayout
    android:id="@+id/video_list_frame"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
</FrameLayout>

<FrameLayout
    android:id="@+id/video_player_frame"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
</FrameLayout>

Yes, I know this adds an additional view to the hierarchy but it doesn't increase the tree depth. For additional performance boost I override onCreateAnimator in my fragments to offload the animation to the hardware layer, like so:

@Override
public Animator onCreateAnimator(int transit, boolean enter, int nextAnim) {
    Animator animation = super.onCreateAnimator(transit, enter, nextAnim);

    // HW layer support only exists on API 11+
    if (Build.VERSION.SDK_INT >= 11) {
        if (animation == null && nextAnim != 0) {
            animation = AnimatorInflater.loadAnimator(getActivity(), nextAnim);
        }

        if (animation != null) {
            animation.addListener(new LayerEnablingAnimatorListener(getView()));
        }
    }

    return animation;
}

And this is LayerEnablingAnimatorListener:

public class LayerEnablingAnimatorListener extends AnimatorListenerAdapter {

    private final View mTargetView;
    private int mLayerType;

    public LayerEnablingAnimatorListener(View targetView) {
        mTargetView = Objects.requireNonNull(targetView, "Target view cannot be null");
    }

    public View getTargetView() {
        return mTargetView;
    }

    @Override
    public void onAnimationStart(Animator animation) {
        super.onAnimationStart(animation);
        mLayerType = mTargetView.getLayerType();
        mTargetView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
    }

    @Override
    public void onAnimationEnd(Animator animation) {
        super.onAnimationEnd(animation);
        mTargetView.setLayerType(mLayerType, null);
    }
}
like image 170
John Busby Avatar answered Oct 20 '22 20:10

John Busby