Фрагмент не заменяется при использовании backstack

У меня есть приложение, использующее навигационный ящик. Ящик позволяет перемещаться между двумя фрагментами: F1 и F2:

Схема деятельности:

<android.support.v4.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <!-- The main content view -->
    <FrameLayout
        android:id="@+id/content_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/background"/>
    <!-- The navigation drawer -->
    <ListView android:id="@+id/left_drawer"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:choiceMode="singleChoice"
        android:dividerHeight="0dp"
        android:background="#f5f5f5"/>

</android.support.v4.widget.DrawerLayout>

Код для замены фрагмента в Activity:

private void selectItem(int position) {
    Fragment fragment;
    fragment = getFragmentToDisplay(position);

    if(fragment != null)
    {
        FragmentManager fragmentManager = getFragmentManager();
        fragmentManager.beginTransaction()
                .replace(R.id.content_frame, fragment,"fragment_"+position)
                .commit();
    }
}

На F1 у меня есть кнопка для вызова другого фрагмента (F3). Когда F3 заменяет F1, я использую addToBackStack(), чтобы иметь возможность вернуться к F1, нажав клавишу возврата.

Замена F1 на F3:

getFragmentManager().beginTransaction()
                .replace(R.id.content_frame, new GameFragment())
                .addToBackStack("Games").commit();

Переход от F1 к F2 , от F2 к F1 работает отлично.
Переход от F1 к F3 , от F3 к F1 (с помощью кнопки «Назад») тоже работает.

Тем не менее, если я выполняю эту последовательность:
F1–F3 с помощью кнопки.
F3–F2 с помощью панели навигации.
F2–F1 с помощью кнопки «Назад» (назад).
F1–F2 с помощью панели навигации.

Последний фрагмент (F2) не заменяет F1, вместо этого он отображается выше, как если бы я его добавил: F2 не заменяет  F1

Выполнение той же навигации, но без использования кнопки «Назад» работает, как и ожидалось.

Почему backstack возится с заменой фрагмента?

Моя цель — обеспечить обратную навигацию между F1 и F3, но не между фрагментами, к которым обращается панель навигации.


person grunk    schedule 15.08.2014    source источник


Ответы (2)


Давайте разберемся, что происходит на каждом шаге:

  • F1 до F3 с помощью кнопки.

Поскольку вызывается addToBackStack, для этой транзакции создается запись обратного стека. В записи заднего стека записаны 2 операции:

op1: удалить F1

op2: добавить F3

  • От F3 до F2 с помощью навигационного ящика.

В случае навигационного ящика вы не использовали addToBackStack, а задний стек совершенно не знает об этой транзакции, в которой F3 удаляется и добавляется F2.

  • От F2 до F1 кнопкой «назад» (backstack).

При нажатии кнопки «Назад» операция последней записанной записи обратного стека будет отменена. Последней записанной записью было удалить F1 и добавить F3. Ожидаемый результат будет следующим:

op1: удалить F1 => добавить F1

op2: добавить F3 => удалить F3

Поскольку F3 уже был удален в предыдущей транзакции, нет операции. Задний стек совершенно не знает о F2 и, следовательно, остается как есть. К концу этой транзакции в окно активности добавляются как F1, так и F2. Поскольку размер F1 больше, чем F2, его не видно.

  • От F1 до F2 по навигационному ящику

Эта транзакция просто поместит F2 поверх F1, так как оба уже были добавлены в окно активности.

Решение. Поскольку обратная навигация должна происходить только между F1 и F3, в тот момент, когда пользователь использует панель навигации для перехода к другому фрагменту, просто очистите задний стек.

FragmentManager fm = getActivity().getFragmentManager();
for(int i = 0; i < fm.getBackStackEntryCount(); i++) {    
    fm.popBackStack();
}
person Manish Mulimani    schedule 29.08.2014

Попробуй это

getFragmentManager().beginTransaction()
                .replace(R.id.content_frame, new GameFragment())
                .addToBackStack(null).commit();
person Sathish    schedule 16.08.2014