Android: общий элемент — обратный переход не работает

Я реализовал переход общего элемента из recyclerview между фрагментами. Переход ввода работает хорошо, но я не знаю, почему переход возврата не работает.

Адаптер RecyclerView из первого фрагмента

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();
      }
    }
  });
}

показать фрагмент();

Я попытался добавить переход выхода и входа в каждый фрагмент, но он все еще не работает, поэтому я установил его на ноль, думая, что у анимации есть конфликты, но проблема все еще существует.

@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

У меня есть это, когда я настраиваю представления

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

и вызвал supportStartPostponedEnterTransition() после того, как я загрузил изображение в представлении:

@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;
    }
  });
}

Кажется, я не знаю, в чем проблема, любая помощь очень ценится, спасибо!


person Ralph    schedule 08.05.2018    source источник


Ответы (2)


KOTLIN с компонентом навигации Android

Для всех, кто здесь ищет ответ на этот вопрос, когда вы используете компонент Android Navigation, вы можете заставить работать анимацию обратного перехода, добавив эти строки в функцию onViewCreated начального фрагмента:

        postponeEnterTransition()
        view.doOnPreDraw { startPostponedEnterTransition() }

Обычно вы должны использовать postponeEnterTransition/startPostponedEnterTransition, если вы открываете второй фрагмент, щелкнув элемент RecyclerView.

person Joe Muller    schedule 24.02.2020
comment
Потрясающий! Я искал это решение некоторое время! - person gpo; 11.12.2020
comment
Если вы используете Java, мне помогло добавление postponeEnterTransition(); OneShotPreDrawListener.add(view, this::startPostponedEnterTransition); в onViewCreated. - person ReefG; 01.06.2021

Мне удалось решить эту проблему, удалив transaction.setReorderingAllowed(true);.

person Ralph    schedule 08.05.2018
comment
Я полагаю, что у вас могут быть неожиданные результаты, если вы удалите setReorderingAllowed, а также, когда у вас есть SharedElementTransitions, вам не нужно явно указывать переход возврата, он автоматический, как только вы укажете переход ввода, возврат является противоположным ему и является устанавливается автоматически. Также вам не нужно проверять версию, которую я считаю, когда вы устанавливаете имя перехода, используя ViewCompat . - person Suleyman; 08.05.2018