Вложенные фрагменты и задний стоп

Поддерживает ли Back Stack взаимодействие с вложенными фрагментами в Android?

Если это так, что я делаю неправильно? В моей реализации кнопка "Назад" полностью игнорирует тот факт, что я добавил эту транзакцию в задний стек. Я надеюсь, что это не из-за проблемы с вложенными фрагментами, а просто с неправильным выполнением.

Следующий код находится внутри одного из моих фрагментов и используется для замены нового фрагмента с любым вложенным фрагментом в настоящее время:

     MyFragment fragment = new MyFragment();
     FragmentTransaction ft = getChildFragmentManager().beginTransaction();
     ft.setCustomAnimations(R.animator.slide_in_from_right, R.animator.slide_out_left, R.animator.slide_in_from_left, R.animator.slide_out_right);
     ft.addToBackStack(null);
     ft.replace(R.id.myFragmentHolder, fragment);
     ft.commit();

Ответ 1

У меня та же проблема, я хотел бы вставить фрагменты и сохранить задний стек для каждого вложенного фрагмента.

Но... похоже, что этот случай не обрабатывается библиотекой поддержки v4. В коде FragmentActivity в библиотеке я могу найти:

public void onBackPressed() {
    if (!mFragments.popBackStackImmediate()) {
        finish();
    }
}

mFragments представляет FragmentManager активности, но не кажется, что этот менеджер "распространяет" поп для менеджеров детей. Обходным путем было бы вручную вызвать popBackStackImmediate() в дочернем менеджере, как это происходит в деятельности, унаследованной от FragmentActivity:

private Fragment myFragmentContainer;

    @Override
    public void onBackPressed() {
            if (!myFragmentContainer.getChildFragmentManager().popBackStackImmediate()) {
                finish(); //or call the popBackStack on the container if necessary
            }
    }

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

Ответ 2

В моем текущем проекте у нас есть несколько "вложенных слоев", поэтому я придумал следующее обходное решение, чтобы автоматически поместить backstack только для менеджеров фрагментов верхнего уровня:

@Override
public void onBackPressed() {
    SparseArray<FragmentManager> managers = new SparseArray<>();
    traverseManagers(getSupportFragmentManager(), managers, 0);
    if (managers.size() > 0) {
        managers.valueAt(managers.size() - 1).popBackStackImmediate();
    } else {
        super.onBackPressed();
    }
}

private void traverseManagers(FragmentManager manager, SparseArray<FragmentManager> managers, int intent) {
    if (manager.getBackStackEntryCount() > 0) {
        managers.put(intent, manager);
    }
    if (manager.getFragments() == null) {
        return;
    }
    for (Fragment fragment : manager.getFragments()) {
        if (fragment != null) traverseManagers(fragment.getChildFragmentManager(), managers, intent + 1);
    }
}

Ответ 3

@Override
public void onBackPressed() {
    FragmentManager fm = getSupportFragmentManager();
    if (fm.getBackStackEntryCount() > 0) {
        fm.popBackStack();
        return;
    }
    finish();
}