Shared element transitions - fragments

2k Views Asked by At

I have pushed my sample app here: https://bitbucket.org/user1010/transitiondemo

I am following master-detail pattern in my app. Master fragment (MyRecyclerFragment / MyListFragment) shows a list of textviews. When user clicks on any of those textviews, details fragment (MyDetailsFragment) is launched. Details fragment has the title (same as the one on which user had clicked).

I am trying to achieve the following transition effect:

  • Explode transition for exiting views
  • Fade transition for appearing views
  • Move / Translation transition for the TextView which is shared between those 2 fragments

Issues:

  • The shared TextView disappears when the transition starts. But the shared transition miraculously works if the first item of the list is clicked.
  • Transition works if details layout is changed. Please see details.xml. If I remove FrameLayout title_bar completely and put TextView title as a direct child of root LinearLayout, shared element transition works perfectly.
  • It seems like epicentre gets changed for shared element return transition. For example, if I click on 7th TextView in the list, exit transition (explode) takes that TextView as epicentre. All the TextViews above it slide up and the TextViews below it slide down. But while returning from details fragment to master fragment, epicentre for the return transition is not the TextView which was clicked.
2

There are 2 best solutions below

1
On

try with this -

set the each row image with different-different transition name -

 @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        View view = convertView;

        if (view == null) {
            view = LayoutInflater.from(getContext()).inflate(R.layout.list_item, null);
        }

        TextView textView = (TextView) view.findViewById(R.id.textView);

        ImageView imageView = (ImageView) view.findViewById(R.id.imageView);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            textView.setTransitionName("transtext" + position);
            imageView.setTransitionName("transition" + position);
        }

        return view;
    }
}

then on item click for example -

 ImageView imageView = (ImageView) view.findViewById(R.id.imageView);
            TextView textView = (TextView) view.findViewById(R.id.smallerImageView);

            EndFragment endFragment = new EndFragment();

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

                imageTransitionName = imageView.getTransitionName();
                textTransitionName = textView.getTransitionName();



 setSharedElementReturnTransition(TransitionInflater.from(
                        getActivity()).inflateTransition(R.transition.change_image_trans));


  setExitTransition(TransitionInflater.from(
                    getActivity()).inflateTransition(android.R.transition.fade));

            endFragment.setSharedElementEnterTransition(TransitionInflater.from(
                    getActivity()).inflateTransition(R.transition.change_image_trans));
            endFragment.setEnterTransition(TransitionInflater.from(
                    getActivity()).inflateTransition(android.R.transition.fade));

            }

 Bundle bundle = new Bundle();

        FragmentManager fragmentManager = getFragmentManager();

            bundle.putString("TRANS_NAME", imageTransitionName);
            bundle.putString("TRANS_TEXT", textTransitionName);
            endFragment.setArguments(bundle);

            fragmentManager.beginTransaction()
                    .replace(R.id.container, endFragment)
                    .addToBackStack("Payment")
                    .addSharedElement(imageView, imageTransitionName)
                    .addSharedElement(textView, textTransitionName)
                    .addSharedElement(staticImage, getString(R.string.fragment_image_trans))
                    .commit();

In EndFragment in oncreate method get the key of transition name and set on the view -

 public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        Bundle bundle = getArguments();
        String actionTitle = "";
        Bitmap imageBitmap = null;
        String transText = "";
        String transitionName = "";

        if (bundle != null) {
            transitionName = bundle.getString("TRANS_NAME");
            actionTitle = bundle.getString("ACTION");
            imageBitmap = bundle.getParcelable("IMAGE");
            transText = bundle.getString("TRANS_TEXT");
        }

        getActivity().setTitle(actionTitle);
        View view = inflater.inflate(R.layout.fragment_end, container, false);

        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            view.findViewById(R.id.listImage).setTransitionName(transitionName);
            view.findViewById(R.id.smallerImageView).setTransitionName(transText);
        }

        ((ImageView) view.findViewById(R.id.listImage)).setImageBitmap(imageBitmap);
        ((TextView) view.findViewById(R.id.smallerImageView)).setText(actionTitle);

        return view;
    }

related https://stackoverflow.com/a/31982516/3150663

Vote my answer up if you got solution. :)

0
On
  • The shared TextView disappears when the transition starts. But the shared transition miraculously works if the first item of the list is clicked.
  • Transition works if details layout is changed. Please see details.xml. If I remove FrameLayout title_bar completely and put TextView title as a direct child of root LinearLayout, shared element transition works perfectly.

It seems the details TextView can't be animated outside of its parent bounds. Try setting clipChildren to false to all parent views of your TextView in your details.xml like this. It's working for me.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:clipChildren="false"
              android:orientation="vertical">

    <FrameLayout
        android:id="@+id/title_bar"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:clipChildren="false">

        <TextView
            android:id="@+id/title"
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:background="@android:color/white"
            android:gravity="center"
            android:text="@string/dummy_title"
            android:textColor="@android:color/black"/>
    </FrameLayout>
    ...
</LinearLayout>