Заменить верхний фрагмент на задний стек

У меня так много проблем с фрагментами Android... Предположим, что мой задний стек выглядит следующим образом:

[C]
[B]
[A]
---

Нажатие кнопки "Назад" отключится Fragment C и оставит Fragment B в верхней части стека. Теперь, как мне поменять Fragment C на Fragment D при сохранении заднего стека? Примечание. Fragment B не отображается во время операции.

[C] <- [D]               [D]
[B]            ----->    [B]
[A]                      [A]
---                      ---

Таким образом, нажатие кнопки "Назад" выскочит Fragment D, а Fragment B сверху. Fragment C полностью удаляется из стека.

Я добавляю каждый фрагмент в стек таким образом

FragmentTransaction ft = manager.beginTransaction();
ft.replace(id, instance, getTag(instance));
ft.addToBackStack(getTag(instance));
ft.commit();

Я думал, что этого можно добиться, выполняя те же самые вызовы без addToBackStack, но только что сделанные Fragment D и Fragment B перекрываются.

Ответ 1

Вы пытались поместить задний стек перед тем, как добавить фрагмент D:

FragmentManager fragmentManager = getFragmentManager();
fragmentManager.popBackStack(); // or popBackStackImmediate();
ft.addToBackStack(<fragmentD>);

Ответ 2

fragmentTransaction.replace предполагается заменить все фрагменты в FragmentManager, а затем добавить новый. В соответствии с Google:

Это по существу то же самое, что вызывать удаление (фрагмент) для всех добавленных в настоящее время фрагментов, которые были добавлены с тем же контейнером, и затем добавить (int, Fragment, String) с теми же аргументами, которые приведены здесь.

Но, как мы видим, он не всегда работает нормально.

(Другой полезный вопрос: FragmentTransaction не работает)

Я использую следующий код (с помощью fragmentManager.getFragments()):

int top = getSupportFragmentManager().getFragments().size()-1;
while (top > 0 && getSupportFragmentManager().getFragments().get(top) == null) {
    top--;
}
getSupportFragmentManager().beginTransaction()
                 .remove(getSupportFragmentManager().getFragments().get(top))
                 .add(R.id.fragment_container, newfrag).commit();

(Я знаю, что не использовал backstack, но я немного смущен этим.)

Ответ 3

Много времени прошло. Я столкнулся с той же проблемой. Мое решение.

    val topFragment = supportFragmentManager.findFragmentByTag(TAG)
    val transaction = supportFragmentManager.beginTransaction()
    if (topFragment != null) {
            val removeTransaction = supportFragmentManager.beginTransaction()
            supportFragmentManager.popBackStack()
            removeTransaction.remove(currentFragment).commitAllowingStateLoss()
    }
    transaction.add(containerId, newFragment, newFragmentTag)
    transaction.addToBackStack(newFragmentTag)
    transaction.commit()