29

The new Shared Element Transitions works when i use Fragment 'replace' but i can't seem to make it work fragment 'add'. I use the same container in both the cases.

More details:

Activity - layout->

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#00ffff"
    android:orientation="vertical" >

</FrameLayout>

On launch of the Activity, I add Fragment1 to the screen

getFragmentManager().beginTransaction().replace(R.id.container,new TransitionTestFragment1(), "TransitionTestFragment1").commit();

On a click event for a view in the layout of Fragment1 -> I add Fragment2 to the screen. I set the listener in the first Fragment's onCreateView

public View onCreateView(LayoutInflater inflater, ViewGroup container,
    Bundle savedInstanceState) {
final TransitionSet transitionSet = new TransitionSet();
transitionSet.addTransition(new ChangeImageTransform());
transitionSet.addTransition(new ChangeBounds());
transitionSet.addTransition(new ChangeTransform());
transitionSet.setDuration(300);

View v=inflater.inflate(R.layout.fragment1, null);
final View image=v.findViewById(R.id.image);
image.setOnClickListener(new OnClickListener() {

    @Override
    public void onClick(View v) {
        setSharedElementReturnTransition(transitionSet);
        Fragment fragment = new TransitionTestFragment2();
        fragment.setSharedElementEnterTransition(transitionSet);

        FragmentTransaction ft = getFragmentManager().beginTransaction()
                .replace(R.id.container, fragment)
                .addToBackStack("transaction")
                .addSharedElement(image, "MyTransition");
        ft.commit();

    }
});
return v;

}

I have this image view in the layouts of both fragments

 <ImageView
        android:layout_width="300dp" 
        android:layout_height="300dp"
        android:src="@drawable/ic_launcher"
        android:transitionName="MyTransition" />

Now, the transition does not work if i use FragmentTransaction.add() to add the second fragment, but it works if i use FragmentTransaction.replace() instead. How can i make it work with add()? Is it possible at all?

Vinay W
  • 9,912
  • 8
  • 41
  • 47
  • 1
    Even i am facing this problem...Did you find a solution ? – Akshay Mahajan Feb 16 '17 at 07:09
  • There is no 'solution'/workaround to this, that i know of.. since the transitions api is built around the principle of re-using views, as stated in @ar34z 's answer. Re-use can only happen when the screen/fragment/activity using a view dies/is paused and one of its views can be re-used in a screen that is about to be launched. When you add a fragment, you can't "re-use" its elements until it dies.. – Vinay W Mar 29 '18 at 09:27

3 Answers3

6

I know this is an old question but recently i had the same problem: .replace was not an option.

I had to use .Hide and .Add and what worked for me was to set:

setReorderingAllowed(true) 

on the transaction.

GiampaoloGabba
  • 1,428
  • 1
  • 15
  • 21
  • i tried this, it worked but when exiting the fragment, the transition animation is not working and the view got invis – JKOU Dec 11 '19 at 15:34
4

I guess it is because the new fragment is placed on top of the old fragment. The old fragment is not being placed out of the controller and onPause (and sequenced methods) aren't being called. It doesn't play any transitions because the old fragment might still be visible to the user (the system doesn't know that).

In my answer (where you commented) I added an enter and exit transition. If you add it, does it even animate? If not, it's probably because of the stated reason.

Community
  • 1
  • 1
ar34z
  • 2,609
  • 2
  • 24
  • 37
  • No, it does not animate when i 'add' it as per your answer. I imagined that would be the reason. Do you have any ideas for a work-around though? Any way i could make this work without having to resort to changing 'add' to 'replace'? Thanks for the answer anyway. – Vinay W Mar 24 '15 at 12:50
  • I wouldn't know. I'd say it's not possible since the system is based on 'resuing' a view. I assume you want to leave all views in your old fragment as they are, and 'reuse' a single view in the new fragment. No idea how complex your new fragment is, otherwise I'd put everything in the layout of the 'old' fragment, animating it myself. But sometimes it is better to make concessions (technical vs design) and either not animate the view, or have fancy animations and no 'visible stack'. If the old fragment doesn't stay visible, why use add and not replace? – ar34z Mar 24 '15 at 13:50
  • 2
    think its not possible too. Looking for a definitive answer so i can move on. Reason why i dont want to use replace is because the old fragment does heavy work (downloading considerably large amount of data to display, has multiple horizontal scroll views) when it is initialised.. due to which onSaveInstanceState/onRestore.. is not smooth enough.. whereas if i just use add, everything works smoothly(as nothing is unloaded from the main memory) – Vinay W Mar 24 '15 at 14:32
-2

It will not animate because the old fragment is still present. For adding you need to hide the previous fragment. Here is the example

For pushing:

    fragmentTransaction.add(R.id.content, fragment);
    if (fragments.size() > 0) {
        UIBaseFragment lastElement = fragments.lastElement();
        fragmentTransaction.hide(lastElement);
    }
    fragmentTransaction.addToBackStack(null);
    fragmentTransaction.commit();
    fragments.push(fragment);

Then pop in this way

    final FragmentManager manager = getChildFragmentManager();
    manager.popBackStack();
    fragments.pop();
faiziii
  • 371
  • 4
  • 11