Фрагмент addToBackStack() и popBackStackImmediate() не работают
В настоящее время я создаю приложение для Android (14 <= SDK <= 21), используя один ActionBarActivity
и более Fragments
, например ListFragment
и MapFragment
, которые меняются в пределах одного FrameLayout
.
ActionBarActivity автоматически заменяет/фиксирует фрагмент A. Затем, когда пользователь нажимает кнопку, хостинг Activity заменяет/фиксирует новый другой фрагмент B. Моя цель - позволить пользователю вернуться к фрагменту A, как только она нажимает кнопка назад.
Некорректный код.
MainActivity
public class MainActivity extends ActionBarActivity implements StopFragment.OnFragmentInteractionListener,
StopItemFragment.OnFragmentInteractionListener {
...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fragmentManager = getFragmentManager();
fragmentManager.enableDebugLogging(true);
...
if (fragmentManager.findFragmentById(R.id.content_frame) == null) {
StopItemFragment list = StopItemFragment.newInstance(null); //A - extends ListFragment
fragmentManager.beginTransaction()
.replace(R.id.content_frame, list)
.addToBackStack(null)
.commit();
}
...
@Override
public void onFragmentInteraction(String id) {
selectItem(Integer.parseInt(id));
}
private void selectItem(int position) {
StopFragment fragment = StopFragment.newInstance(null, null); //B - extends Fragment
...
fragmentManager.beginTransaction()
.replace(R.id.content_frame, fragment)
.commit();
...
}
}
Проблема
Даже если вызывается addToBackStack()
, когда я нахожусь на фрагменте B, я не могу вернуться к фрагменту A. MainActivity напрямую закрыт.
Тем не менее я пытался управлять задним стеклом сам по себе, не повезло. Я вижу, что фрагмент находится в стеке, но если я вызываю popBackStackImmediate()
, фрагмент A выскочит и транзакция фрагмента не будет выполнена. (первая обратная печать ничего не происходит, вторая активность закрыта)
Я также прикрепляю logcat FragmentManager:
http://pastebin.com/hFLHprL8
Ответы
Ответ 1
Для тех, кто все еще ищет решение.
В основном классе Activity
(который размещает фрагменты) просто переопределяет onBackPressed()
.
@Override
public void onBackPressed() {
if (getFragmentManager().getBackStackEntryCount() > 0 ){
getFragmentManager().popBackStack();
} else {
super.onBackPressed();
}
}
В фрагменте нет метода onBackPressed()
, и этот метод предназначен только для Activity
. Итак, когда мы нажимаем клавишу "назад", отображается поведение по умолчанию Activity
, которое равно
вы либо перейдете к предыдущему действию (если есть), либо к приложению выйдет.
Теперь нам нужно переопределить этот метод, чтобы сообщить Activity
, что, когда мы нажимаем клавишу "Назад", если есть какие-либо фрагменты в стеке, вытащите их (и это произойдет, когда addToBackStack()
появится на картинке). В противном случае выполните поведение по умолчанию.
Ответ 2
Попробуйте это (Примечание добавить не заменить для фрагмента А и addToBackStack() для фрагмента B)
StopItemFragment list = StopItemFragment.newInstance(null); //A - extends ListFragment
fragmentManager.beginTransaction()
.add(R.id.content_frame, list)
.commit();
и
StopFragment fragment = StopFragment.newInstance(null, null); //B - extends Fragment
...
fragmentManager.beginTransaction()
.replace(R.id.content_frame, fragment)
.addToBackStack("FragmentB")
.commit();
Ответ 3
Мне пришлось называть beginTransaction()
и commit()
of FragmentManager
вручную.
Решено путем переопределения onBackPressed()
:
@Override
public void onBackPressed() {
...
if (fragmentManager.getBackStackEntryCount() > 1){
fragmentManager.popBackStackImmediate();
fragmentManager.beginTransaction().commit();
} else {
//handle finish
finish(); // Closes app
}
}
Ответ 4
Если вы боретесь с addToBackStack() и popBackStack(), просто используйте
FragmentTransaction ft =getSupportFragmentManager().beginTransaction();
ft.replace(R.id.content_frame, new HomeFragment(), "Home");
ft.commit();`
В вашей деятельности В OnBackPressed() найдите мерцание по тегу, а затем сделайте свой материал
Fragment home = getSupportFragmentManager().findFragmentByTag("Home");
if (home instanceof HomeFragment && home.isVisible()) {
// do you stuff
}
Для получения дополнительной информации https://github.com/DattaHujare/NavigationDrawer
Я никогда не использую addToBackStack() для обработки фрагмента.
Ответ 5
причина, по которой popBackStack()
и popBackStackImmediatly()
связаны с тем, что вы не добавили этот фрагмент (который вы хотите выложить) в backStack. Чтобы сделать это, вы должны сделать вызов addToBackStack() в момент совершения транзакции, чтобы добавить/заменить ваш фрагмент.
Ответ 6
Прежде всего, я хотел бы сказать большое спасибо за выделенный ответ [Ник] (Низкая репутация не может комментировать внизу), за то, что он помог мне узнать, действительно ли было то, что не упоминалось в Документации Android.
Во-вторых, сейчас 2019 год, и после того, как я наткнулся на аналогичный путь в настройках Androidx, я долго не мог ничего найти, пока не проверил и этот вопрос, и официальный пример кода в Kotlin, который этот вопрос привел к разгадке, и пример кода в моем случае был решением, работающим как брелок с очень маленьким кусочком перезаписи, надеюсь, он также поможет тем, кто ищет официальное решение
@Override
public boolean onSupportNavigateUp() {
if (getSupportFragmentManager().popBackStackImmediate()){
return true;
}
return super.onSupportNavigateUp();
}
Вышеупомянутый код на Java (снимок экрана)
Постскриптум Мой первый ответ нИКОГДА о stacksoverflow после более чем 5-летнего использования ^^