Ralph
Ralph

Reputation: 578

Android: Shared Element - return transition not working

I implemented a shared element transition from a recyclerview between to fragments. The enter transition works well but I don't know why the return transition isn't working.

Adapter of the RecyclerView from first fragment

public void onBindViewHolder(@NonNull final MenuItemViewHolder holder, int position)
{
  holder.setData(category, data.get(holder.getAdapterPosition()));
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
  {
    MenuItem item = data.get(holder.getAdapterPosition());
    ViewCompat.setTransitionName(holder.name, item.getName());
    ViewCompat.setTransitionName(holder.image, item.getImage());
    ViewCompat.setTransitionName(holder.price, item.getId());
  }

  holder.setViewClick(new View.OnClickListener()
  {
    @Override
    public void onClick(View v)
    {
      try
      {
        if (context != null)
        {
          if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
          {
            showFragment(category, data.get(holder.getAdapterPosition()), holder.name, holder.price, holder.image, holder.isLoaded());
          }
          else
          {
            Gson gson = new Gson();
            Bundle bundle = new Bundle();
            bundle.putString(Values.CAT_DATA, gson.toJson(category));
            bundle.putString(Values.ITM_DATA, gson.toJson(data.get(holder.getAdapterPosition())));
            ((MainActivity) context).showFragment(ProductViewFragment.class, null, bundle);
          }
        }
      }
      catch (NullPointerException | ClassCastException e)
      {
        e.printStackTrace();
      }
    }
  });
}

showFragment();

I tried adding exit and entry transition in each fragments but it still doesn't work so I've set it to null thinking the animations are having conflicts but the problem is still existing.

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void showFragment(MenuCategory category, MenuItem menuItem, TextView name, TextView price,
  ImageView image, boolean isLoaded)
{
  try
  {
    if (context != null)
    {
      if (fragment != null)
      {
        //current fragment
        this.fragment.setSharedElementReturnTransition(
          TransitionInflater.from(context).inflateTransition(android.R.transition.move));
        this.fragment.setExitTransition(null);
      }

      ProductViewFragment fragment = ProductViewFragment.newInstance(category, menuItem, isLoaded);
      //next fragment
      fragment.setEnterTransition(null);
      fragment.setSharedElementEnterTransition(
        TransitionInflater.from(context).inflateTransition(android.R.transition.move));

      FragmentManager manager = ((MainActivity) context).getSupportFragmentManager();
      if (manager != null)
      {
        FragmentTransaction transaction = manager.beginTransaction();
        transaction.setReorderingAllowed(true);
        transaction.addSharedElement(name, ViewCompat.getTransitionName(name));
        transaction.addSharedElement(price, ViewCompat.getTransitionName(price));
        transaction.addSharedElement(image, ViewCompat.getTransitionName(image));
        transaction.replace(R.id.container, fragment);
        transaction.addToBackStack(null);
        transaction.commit();
      }
    }
  }
  catch (NullPointerException | ClassCastException e)
  {
    e.printStackTrace();
  }
}

ProductViewFragment

I have this when I setup the views

ViewCompat.setTransitionName(name, menuItem.getName());
ViewCompat.setTransitionName(image, menuItem.getImage());
ViewCompat.setTransitionName(price, menuItem.getId());

and called supportStartPostponedEnterTransition() after I loaded the image in the view:

@Override
public void onLoadingComplete(String imageUri, final View view, Bitmap loadedImage)
{
  view.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener()
  {
    @Override
    public boolean onPreDraw()
    {
      if (getActivity() != null)
      {
        view.getViewTreeObserver().removeOnPreDrawListener(this);
        getActivity().supportStartPostponedEnterTransition();
      }
      return true;
    }
  });
}

I don't seem to know where the problem is, any help is much appreciated thanks!

Upvotes: 2

Views: 4621

Answers (2)

Code on the Rocks
Code on the Rocks

Reputation: 17824

KOTLIN with Android Navigation Component

For anyone who's here looking for the answer to this question when you're using the Android Navigation component, you can make the reverse transition animation work by adding these lines to the onViewCreated function of the starting fragment:

        postponeEnterTransition()
        view.doOnPreDraw { startPostponedEnterTransition() }

You would generally use postponeEnterTransition/startPostponedEnterTransition if you are opening the second fragment by clicking on a RecyclerView item.

Upvotes: 11

Ralph
Ralph

Reputation: 578

I managed to solve it by removing transaction.setReorderingAllowed(true);.

Upvotes: 0

Related Questions