4

Is there any way to use a shared element transitions from a fragment inside a ViewPager into a new Fragment?

EDIT

I have a MainActivity with the ViewPager that holds FragmentA. From that I want to open FragmentB with a Shared Element Transition.

I've created a sample project which you can see below. The shared element transition is working fine if I remove the ViewPager and open FragmentA regularly, but as soon as I add the ViewPager to the project, no transition appears.

This is the code for MainActivity

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    ViewPager mViewPager = (ViewPager)findViewById(R.id.viewpager);

    FragmentPagerAdapter adapter = new FragmentPagerAdapter(getSupportFragmentManager()) {
        private int NUM_ITEMS = 1;
        @Override
        public Fragment getItem(int position) {
            switch (position) {
                case 0:
                    return new FragmentA();
                default:
                    return null;
             }
        }
        @Override
        public int getCount() {
            return NUM_ITEMS;
        }
    };
    mViewPager.setAdapter(adapter);
    }
}

XML for MainActivity

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.gustafwennerstrom.testeb.MainActivity">
    <android.support.v4.view.ViewPager
        android:layout_width="match_parent"
        android:id="@+id/viewpager"
        android:layout_height="match_parent">
    </android.support.v4.view.ViewPager>
</RelativeLayout>

This is the code for FragmentA

public class FragmentA extends Fragment {
    FrameLayout root;

    public FragmentA() {}

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
        root = (FrameLayout)inflater.inflate(R.layout.fragment_, null);
        ImageView image = (ImageView) root.findViewById(R.id.testImage);
        image.setOnClickListener(openFragment);
        return root;

    }

    private View.OnClickListener openFragment = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            ImageView sharedImage = (ImageView)root.findViewById(R.id.testImage);
            getFragmentManager()
                .beginTransaction()
                .addSharedElement(sharedImage, ViewCompat.getTransitionName(sharedImage))
                .addToBackStack(getTag())
                .replace(android.R.id.content, new FragmentB())
                .commit();
    };
}

XML for FragmentA (FragmentB looks very similar)

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/fragment_a"
    android:background="@color/colorAccent"
    tools:context="com.example.gustafwennerstrom.testeb.FragmentA">
    <ImageView
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:background="@drawable/yo"
        android:transitionName="myImage"
        android:id="@+id/testImage"/>
</FrameLayout>

This is fragmentB

public class FragmentB extends Fragment {
    public FragmentB() {}

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            setSharedElementEnterTransition(TransitionInflater
            .from(getContext())
            .inflateTransition(android.R.transition.move)
            .setDuration(100));
         }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_fragment_b, container, false);

    }
}

And in styles.xml I've added this line of code:

<item name="android:windowContentTransitions">true</item>
gugge
  • 918
  • 1
  • 11
  • 17
  • 1
    Why not? What issue are you having? – MidasLefko Jul 24 '17 at 15:49
  • No transition appears. It appears only if I open the fragment outside the ViewPager – gugge Jul 24 '17 at 15:55
  • Is [this](https://stackoverflow.com/questions/30628543/fragment-shared-element-transitions-dont-work-with-viewpager?rq=1) your question? – MidasLefko Jul 25 '17 at 12:41
  • Yes. I've tried the solution from there, but I guess I'm doing something wrong. As I understand I need to tell the program to wait with the transition with _postponeEnterTransition_ in MainActivity. Then when the shared view in FragmentB are created, I could call _startPostponedEnterTransition_. But my problem remains... @MidasLefko – gugge Jul 25 '17 at 12:57
  • There are two issues in that question... – MidasLefko Jul 25 '17 at 13:32
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/150095/discussion-between-midaslefko-and-gugge). – MidasLefko Jul 25 '17 at 13:44

1 Answers1

1

Solution/workaround

Alright, I gave up getting this to work between fragments that holds a ViewPager. From this thread we can see that:

The Fragmnets in ViewPager load with a delay, meaning that the activity returns a lot faster than its fragments which are contained inside the ViewPager

Because of that I needed to delay the transition until the content is loaded. To delay the transition I couldn't use postponeEnterTransition () because I did couldn't use makeSceneTransitionAnimation(Activity, android.util.Pair[]) when loading Fragments, only Activities. From docs:

startPostponedEnterTransition() must be called to allow the Activity to start the transitions. If the Activity did not use makeSceneTransitionAnimation(Activity, android.util.Pair[]), then this method does nothing.

I changed my FragmentB to an Activity and now it's working fine! Feel free to post if you find a solution where you can make the transition from within a ViewPager to a Fragment.

gugge
  • 918
  • 1
  • 11
  • 17