Пропустить некоторые фрагменты onBackPressed

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

У меня есть куча фрагментов с использованием одного действия в качестве хоста.

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

Frag1 → (Нажмите Далее) → Frag2 → (Нажмите Далее) → Frag3 → (Нажмите Назад) → Frag1

После прохождения серии фрагментов я хотел бы пропустить некоторые предыдущие фрагменты (в этом случае пропустить Frag 2) при нажатии кнопки "Назад".

Однако, в моем текущем коде, моя проблема в том, что, хотя он возвращается к Frag1, Frag3 не исчезает с экрана. Случается, что Frag1 и Frag3 становятся видимыми друг над другом.

Вот мои соответствующие фрагменты кода:

Фрагмент кода для создания Frag1

@Override
public void onNavigationDrawerItemSelected(int position) {
    // update the main content by replacing fragments
    // init the fragment (with a default fragment, not null)
    Fragment fragment = PlaceholderFragment.newInstance(position + 1);
    // Position number from navigation sidebar starts from 0.
    // Since position starts from 0, add 1 to match section number
    // as implemented in {@link #onSectionAttached()}
    switch(position) {
        case 0:
            fragment = PlaceholderFragment.newInstance(position + 1);
            break;
        case 1: // Frag1 case
            fragment = new AddPointsFragment().newInstance(position + 1, "");
            break;
        default:
            break;
    }
    // update the main content by replacing fragments
    FragmentManager fragmentManager = getFragmentManager();
    // clear all fragments from previous section from the back stack
    fragmentManager.popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
    // replace all currently added fragments in container and replace with the new fragment
    fragmentManager.beginTransaction()
            .replace(R.id.container, fragment)
            .commit();
}

Фрагмент кода для создания Frag2

public void onEnterButtonFragmentInteraction(int sectionNumber, String cardNo) {
    // TODO: Add point for given card number
    int points = 5; //sample points
    AddPointsSuccessFragment addPointsSuccessFragment =
            new AddPointsSuccessFragment().newInstance(sectionNumber, cardNo, points);
    FragmentManager fragmentManager = getFragmentManager();
    fragmentManager.beginTransaction()
            .replace(R.id.container, addPointsSuccessFragment)
            .addToBackStack(null)
            .commit();
}

Фрагмент кода для создания Frag3

public void onOkButtonFragmentInteraction(int sectionNumber, String cardNo, int points) {
    RedeemRewardFragment redeemRewardFragment =
                new RedeemRewardFragment().newInstance(sectionNumber, cardNo, points);
        FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
        fragmentTransaction.replace(R.id.container, redeemRewardFragment);
        fragmentTransaction.commit();
}

Моим текущим обходным путем для этого является добавление .addToBackStack(null) в создание Frag3 и запуск этого кода

public void onBackButtonFragmentInteraction() {
    this.onBackPressed(); // simulate pressing of activity back button
    FragmentManager fragmentmanager = getFragmentManager();
    fragmentmanager.popBackStack(); // pop Frag2 from back stack
}

сразу после вызова метода onBackPressed(). К сожалению, это обходное решение является уродливым, поскольку потому, что перед тем, как перейти к Frag1, возникает фрагментация Frag2.

Ответ 1

Итак, ключом к вашему решению является этот парень:

.addToBackStack(null)

Вместо нуля вы можете передать идентификатор String для этой конкретной транзакции - например, имя класса Fragment - это то, что мы используем (хотя это не работает, если у вас есть несколько экземпляров одного и того же фрагмента на backstack):

.addToBackStack(Fragment1.class.getName())

Затем, если вы хотите вернуться к Fragment1 из Fragment3, просто введите идентификатор следующего фрагмента и передайте флаг INCLUSIVE (что означает, что он также поместит этот следующий фрагмент, который вы указали ):

getFragmentManager().popBackStack(
        Fragment2.class.getName(), 
        FragmentManager.POP_BACK_STACK_INCLUSIVE);

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

Ответ 2

Вы можете попробовать это, он должен работать и не дает сплит-секундной задержки. Его не красивый код, хотя, и если у кого-то есть лучший способ, напишите.

1.Выполните тег для своих фрагментов.

transaction.add(R.id.main_activity_container, FirstFragment, "FirstFragment");
transaction.replace(R.id.main_activity_container, Second, "SECOND");
transaction.replace(R.id.main_activity_container, Third, "THIRD");

2. Модифицируйте свою onBackPressed() в вашей frameActivity (активности), которая "хранит" ваши фрагменты.

@Override
public void onBackPressed() {
    // TODO Auto-generated method stub

    int lastStack = getSupportFragmentManager().getBackStackEntryCount();
    try {
        //If the last fragment was named/tagged "three"
        if (getSupportFragmentManager().getFragments().get(lastStack).getTag().equalsIgnoreCase("THIRD")){

            getSupportFragmentManager().popBackStackImmediate();
            getSupportFragmentManager().popBackStackImmediate();

            //Get your first fragment that you loaded in the beginning. 
            Fragment first = getSupportFragmentManager().findFragmentByTag("FirstFragment");
            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
            transaction.replace(R.id.main_activity_container, first);
            transaction.commit();
            return;
        }
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    super.onBackPressed();
}

Ответ 3

Когда вы показываете Frag2, используйте:

final FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.addToBackStack(FRAG_2);
fragmentTransaction.replace(containerID, frag2, FRAG2_TAG);

и нажмите "Назад":

@Override
public void onBackPressed() {
   final Frag2 frag2 = (Frag2)getSupportFragmentManager().findFragmentByTag(FRAG2_TAG);
   if (frag2 != null && frag2.isVisible() && getSupportFragmentManager().getBackStackEntryCount() > 0) {
    getSupportFragmentManager().popBackStackImmediate();
    return;
   }
}

Это предотвратит отображение frag2 после вызова onBackPressed(). Избегайте использования popBackStack(), так как это приведет к запуску жизненного цикла frag2 (onCreate, onStart, onResume...)