Скажем, у меня есть активность, в которой фрагменты добавлены программно:
private void animateToFragment(Fragment newFragment, String tag) { FragmentTransaction ft = getFragmentManager().beginTransaction(); ft.replace(R.id.fragment_container, newFragment, tag); ft.addToBackStack(null); ft.commit(); }
Каков наилучший способ вернуться к предыдущему фрагменту, который был видимым?
Я обнаружил , что функция кнопки «Триггер» при нажатии кнопки на Android, но я думаю, что симуляция события «назад» не является правильным способом (и я не могу заставить его работать):
dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK));
Calling finish()
просто закрывает активность, которая мне не интересна.
Есть ли лучший способ сделать это?
Посмотрите на getFragmentManager().popBackStack()
(их можно выбрать)
http://developer.android.com/reference/android/app/FragmentManager.html#popBackStack ()
Чтобы рассказать о других полученных ответах, это мое решение (помещено в действие):
@Override public void onBackPressed(){ FragmentManager fm = getFragmentManager(); if (fm.getBackStackEntryCount() > 0) { Log.i("MainActivity", "popping backstack"); fm.popBackStack(); } else { Log.i("MainActivity", "nothing on backstack, calling super"); super.onBackPressed(); } }
Когда мы обновляем / добавляем фрагменты,
Должен включать .addToBackStack ().
getSupportFragmentManager().beginTransaction() .add(detailFragment, "detail") // Add this transaction to the back stack (name is an optional name for this back stack state, or null). .addToBackStack(null) .commit();
После этого, если мы дадим getFragments.popBackStackImmediate (), вернем true, если мы добавим / обновим фрагменты и вернемся к текущему экрану.
replace()
делает 2 вещи:
Эти 2 операции – это то, что сохраняется как запись / транзакция Backstack. Обратите внимание, что фрагмент A остается в created
состоянии, и его представление уничтожено.
Теперь popBackStack()
отменяет вашу последнюю транзакцию, добавленную в BackStack.
В этом случае это будет 2 шага:
После этого фрагмент B detached
, и если вы не будете ссылаться на него, это будет собирать мусор.
Чтобы ответить на первую часть вашего вопроса, нет onCreate()
, потому что FragmentB остался в created
состоянии. И ответ на вторую часть вопроса немного длиннее.
Во-первых, важно понимать, что вы фактически не добавляете Fragments
в Backstack, вы добавляете FragmentTransactions
. Поэтому, когда вы думаете, что вы «замените фрагментом B, добавив фрагмент A в задний стек», вы фактически добавите всю эту операцию в стопку – это замена A на B. Эта замена состоит из двух действий – удалите A и добавьте B ,
Затем, следующий шаг – всплытие транзакции, которая содержит эту замену. Таким образом, вы не выходите из FragmentA, вы меняете «удалить A, добавьте B», который обратный – «удалить B, добавить A».
И тогда последний шаг должен быть яснее – нет B, о котором знает FragmentManager, поэтому, добавив его, заменив A на B на последнем шаге, B должен пройти его ранние методы жизненного цикла – onAttach()
и onCreate()
.
Приведенный ниже код иллюстрирует, что происходит.
FragmentManager fm = getFragmentManager(); FragmentA fragmentA = new FragmentA(); FragmentB fragmentB = new FragmentB(); // 1. Show A fm.beginTransaction() .add(fragmentA, R.id.container) .commit(); // 2. Replace A with B // FragmentManager keeps reference to fragmentA; // it stays attached and created; fragmentB goes // through lifecycle methods onAttach(), onCreate() // and so on. fm.beginTransaction() .replace(fragmentB, R.id.container) .addToBackstack(null) .commit(); // 2'. Alternative to replace() method fm.beginTransaction() .remove(fragmentA) .add(fragmentB, R.id.container) .addToBackstack(null) .commit(); // 3. Reverse (2); Result - A is visible // What happens: // 1) fragmentB is removed from container, it is detached now; // FragmentManager doesn't keep reference to it anymore // 2) Instance of FragmentA is placed back in the container // Now your Backstack is empty, FragmentManager is aware only // of FragmentA instance fm.popBackStack(); // 4. Show B // Since fragmentB was detached, it goes through its early // lifecycle methods: onAttach() and onCreate(). fm.beginTransaction() .replace(fragmentB, R.id.container) .addToBackstack(null) .commit();
Добавьте эти строки в метод onBackPressed (). Метод popBackStackImmediate () вернет вас к предыдущему фрагменту, если у вас есть фрагмент на back stack `
if(getFragmentManager().getBackStackEntryCount() > 0){ getFragmentManager().popBackStackImmediate(); } else{ super.onBackPressed(); }
`
Программно вернуться к предыдущему фрагменту, используя следующий код.
if ( getFragmentManager().getBackStackEntryCount() > 0) { getFragmentManager().popBackStack(); return; } super.onBackPressed();