Фрагментные транзакции с переходом - требуются уникальные имена перехода

Я хочу перейти от представления списка к подробному представлению, и поэтому я использую следующий OnClickListener в своем списке:

@Override
public void onClick(View view)
{
    Bet bet = (Bet)view.getTag();
    FragmentManager fm = getActivity().getSupportFragmentManager();
    BetDetailFragment f = BetDetailFragment.create(bet);
    String tag = f.getClass().getName();

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
    {
        setSharedElementReturnTransition(TransitionInflater.from(getActivity()).inflateTransition(android.R.transition.move));
        f.setSharedElementEnterTransition(TransitionInflater.from(getActivity()).inflateTransition(android.R.transition.move));
    }

    FragmentTransaction ft = fm.beginTransaction()
            .replace(R.id.frame_container, f, tag)
            .addToBackStack(tag);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
    {
        L.d(this, "TRANS: " + TransitionUtil.getTransitionNameBetLogo1(bet) + "|" + view.findViewById(R.id.ivLogo1));
        L.d(this, "TRANS: " + TransitionUtil.getTransitionNameBetLogo2(bet) + "|" + view.findViewById(R.id.ivLogo2));
        ft.addSharedElement(view.findViewById(R.id.ivLogo1), "1");//TransitionUtil.getTransitionNameBetLogo1(bet));
        ft.addSharedElement(view.findViewById(R.id.ivLogo2), "2");//TransitionUtil.getTransitionNameBetLogo2(bet));
    }
    ft.commit();
}

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

java.lang.IllegalArgumentException: Unique transitionNames are required for all sharedElements
        at android.support.v4.app.BackStackRecord.addSharedElement

РЕДАКТИРОВАТЬ

Без общих элементов все работает отлично...

Ответы

Ответ 1

Проблема заключается в том, что addSharedElement НЕ устанавливает имя транзакции для представления!

Поэтому в моем примере мне пришлось бы установить его с помощью следующего кода:

ViewCompat.setTransitionName(view.findViewById(R.id.ivLogo1), "1");
ViewCompat.setTransitionName(view.findViewById(R.id.ivLogo2), "2");

Перед добавлением этих представлений в FragmentTransaction...

Впоследствии следующие работы просто прекрасны и как ожидалось:

ft.addSharedElement(view.findViewById(R.id.ivLogo1), "1");
ft.addSharedElement(view.findViewById(R.id.ivLogo2), "2");

Ответ 2

Вам нужно только установить имя transitionName в свой общий элемент. Нет необходимости выбирать его точно так же, как имя вашего общего элемента (который был передан как второй аргумент метода addSharedElement()).

Это имя (второй параметр addSharedElement()) ДОЛЖЕН быть равно transitionName общего элемента в целевом фрагменте. См. Здесь.


Так что достаточно вставить:

ViewCompat.setTransitionName(view.findViewById(R.id.ivLogo1), "AnyThing");
ViewCompat.setTransitionName(view.findViewById(R.id.ivLogo2), "EveryThing");

перед addSharedElement(...).

Ответ 3

Если onClickListener является частью вашего фрагмента, а не родительская Activity, то вы делаете вещи неправильно здесь. Ваш фрагмент должен уведомлять родительскую активность о том, чего она хочет, и Activty должна иметь дело с ней (т.е. Путем замены фрагментов и т.д.). Фрагмент никогда не должен делать это сам по себе. Кроме того, если вам нужно только перейти от подробного представления к списку, я предполагаю, что вы ввели свой подробный вид из этого списка. Если это так, все, что вам нужно, - вырезать последний элемент (фрагмент фрагмента фрагмента) из предыдущего стека. См. Https://developer.android.com/reference/android/app/FragmentManager.html.

Ответ 4

перед onClick

используйте этот код

ViewCompat.setTransitionName(holder.ivImage, "value");