Android: возврат к предыдущему фрагменту на задней панели
Я реализовал навигационный ящик, который является подклассом Activity. У меня много фрагментов в моем приложении. Мой вопрос здесь.
Предположим, что есть 3 фрагмента:
Fragment_1: Fragment_2: Fragment_3
Когда я запускаю свое приложение, Fragment_1 загружается
Когда я нажимаю на некоторые компоненты на Fragment_1, я перехожу к Fragment_2 и т.д.
Так что это нравится
Fragment_1 > Fragment_2 > Fragment_3
Когда я нажимаю клавишу Fragment_2, я возвращаюсь к Fragment_1
Но когда я нажимаю клавишу Fragment_3, я снова перехожу к Fragment_1 (вместо Fragment_2)
Я хочу, чтобы что-то вроде этого в моем приложении на кнопке Back Key
Fragment_1 < Fragment_2 < Fragment_3
Я использовал Fragment, FragmentManager, FragmentTransaction следующим образом:
MyFragment fragment = new MyFragment();
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).addToBackStack(null)commit();
и я попробовал переопределить onBackPressed() в моей MainActivity:
@Override
public void onBackPressed() {
getFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
int count = getFragmentManager().getBackStackEntryCount();
if (count == 0)
super.onBackPressed();
}
Ответы
Ответ 1
Обновите свой метод Activity#onBackPressed()
, чтобы:
@Override
public void onBackPressed() {
if (getFragmentManager().getBackStackEntryCount() > 0) {
getFragmentManager().popBackStack();
} else {
super.onBackPressed();
}
}
Причина, по которой ваша реализация не работает, заключается в том, что метод FragmentManager#popBackStack()
является асинхронным и не происходит сразу после его вызова.
Из документации:
Эта функция асинхронна - она помещает запрос в pop, но действие не будет выполняться до тех пор, пока приложение не вернется в цикл событий.
Ссылка: http://developer.android.com/reference/android/app/FragmentManager.html#popBackStack(java.lang.String,%20int)
Ответ 2
Вы должны реализовать свою собственную реализацию backstack, как описано здесь.
Отдельный задний стек для каждой вкладки в Android с помощью фрагментов
Вы можете вызвать popFragments() всякий раз, когда вы нажимаете кнопку "Назад" в фрагменте и вызываете pushFragments() всякий раз, когда вы перемещаетесь от одного фрагмента к другому.
в Short,
public void onBackPressed()
{
FragmentManager fm = getActivity().getSupportFragmentManager();
fm.popBackStack();
}
Ответ 3
Тройка находится в FragmentManager#executePendingTransactions();
.
Это то, что я использую для вложенных фрагментов...:
/**
* if there is a fragment and the back stack of this fragment is not empty,
* then emulate 'onBackPressed' behaviour, because in default, it is not working.
*
* @param fm the fragment manager to which we will try to dispatch the back pressed event.
* @return {@code true} if the onBackPressed event was consumed by a child fragment, otherwise
*/
public static boolean dispatchOnBackPressedToFragments(FragmentManager fm) {
List<Fragment> fragments = fm.getFragments();
boolean result;
if (fragments != null && !fragments.isEmpty()) {
for (Fragment frag : fragments) {
if (frag != null && frag.isAdded() && frag.getChildFragmentManager() != null) {
// go to the next level of child fragments.
result = dispatchOnBackPressedToFragments(frag.getChildFragmentManager());
if (result) return true;
}
}
}
// if the back stack is not empty then we pop the last transaction.
if (fm.getBackStackEntryCount() > 0) {
fm.popBackStack();
fm.executePendingTransactions();
return true;
}
return false;
}
и в моем onBackPressed
:
if (!FragmentUtils.dispatchOnBackPressedToFragments(fm)) {
// if no child fragment consumed the onBackPressed event,
// we execute the default behaviour.
super.onBackPressed();
}
Ответ 4
Используйте этот код при изменении вкладок в своем основном действии, чтобы очистить стек.
int count = getFragmentManager().getBackStackEntryCount();
if(count>0){
for (int i = 0; i <count; i++) {
getFragmentManager().popBackStack();
}
}
Затем в ответ на нажатие основной операции сделайте это
int count = getFragmentManager().getBackStackEntryCount();
if (count == 0) {
super.onbackpressed();
}
else {
getFragmentManager().popBackStack();
}
}
Ответ 5
Здесь работает и проверен код, это поможет вам
private static final int TIME_INTERVAL = 2000;
private long mBackPressed;
private void applyExit() {
if (mBackPressed + TIME_INTERVAL > System.currentTimeMillis()) {
finish();
} else {
Toast.makeText(this,"Press Again to exit",Toast.LENGTH_LONG).show();
}
mBackPressed = System.currentTimeMillis();
}
@Override
public void onBackPressed() {
fm = getSupportFragmentManager();
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
}
if (fm.getFragments().size() <= 1) {
applyExit();
} else {
for (Fragment frag : fm.getFragments()) {
if (frag == null) {
applyExit();
return;
}
if (frag.isVisible()) {
FragmentManager childFm = frag.getChildFragmentManager();
if (childFm.getFragments() == null) {
super.onBackPressed();
return;
}
if (childFm.getBackStackEntryCount() > 0) {
childFm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
return;
} else {
fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
return;
}
}
}
}
}