PopBackStack, но сохраните первый фрагмент в android
Я работаю над транзакцией фрагментов, а стопка backstack выглядит так:
fragA => fragB => fragC => fragD
Я хотел бы вернуться к fragA после того, как от fragD
fragD => onBackPress => fragA
Итак, я попробовал код вроде:
getChildFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
но он очищает все задние части, как я могу сохранить первый фрагмент в backstack? Большое спасибо
Ответы
Ответ 1
например. вы можете сделать следующее:
- добавить fragA, не добавляя его в backStack. Так что всегда в
и не будет реагировать на кнопку "Назад".
- когда вы открываете fragD, вы должны очистить фрагмент BackStack. Поэтому, когда вы нажимаете кнопку "Назад" из D frag, вы возвращаетесь к A.
P.S. Существуют и другие способы, как делать то, что вы хотите. Это зависит...
Ответ 2
Поскольку "задний стек" имеет поведение, подобное стеку... последний раз, сначала... последний фрагмент, добавленный в задний стек, сначала выскочит из предыдущего стека. Вам нужно будет выполнить поведение, которое вам требуется вручную, указав свой собственный. Это не так сложно с помощью методов класса FragmentManager
.
Если вы "пометите" свои фрагменты, добавив их в транзакцию...
fragmentTransaction.add(new FragmentA(), "FragmentA_Tag");
вы можете позже определить, какой фрагмент будет отображаться при нажатии кнопки "Назад"...
FragmentA f = fragmentManager.findFragmentByTag("FragmentA_Tag");
if(f != null){
f.show();
}
Как вы определяете, какой фрагмент будет показан вам полностью. Вы можете отслеживать текущий видимый фрагмент, или вы можете использовать метод isHidden
класса Fragment
... BTW, я ' m говорит о нативных фрагментах здесь, а не поддерживает фрагмент библиотеки.
Ответ 3
Столбец содержит записи о транзакциях, а не фрагменты.
Поэтому вы не должны добавлять первую запись транзакции (null → fragA) в backstack.
И все остальные записи транзакций должны быть добавлены в backstack.
В этом случае вы заготовки popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
android удалили все фрагменты, кроме fragA, потому что нет никаких записей о том, как был добавлен fragA.
Ответ 4
Только несколько дней назад я начинаю изучать фрагменты в Android. И я столкнулся с этой проблемой. Здесь я показываю свое решение и как я это разрешаю. Пожалуйста, исправьте, если мой код неправильный. Что мы имеем в это время? Acivity, много фрагментов и их backstack. Мы хотим открыть каждый фрагмент из меню Ящика и очистить все остальные фрагменты из backstack. Но мы должны держать только один фрагмент дома. Когда мы остаемся на домашнем фрагменте, а пользователь нажимает кнопку "Назад", приложение закрывается.
Activity.class
protected void onCreate(Bundle savedInstanceState)
{
...
// adding Home fragment without adding transaction into backstack
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction ft = manager.beginTransaction();
ft.replace(R.id.container, HomeFragment.newInstance("args"), null);
ft.commit();
}
@Override
public void onBackPressed() {
if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
finish();
}
}
public void addFragmentFromMenu(Fragment fragment){
String backStateName = fragment.getClass().getName();
clearBackStack();
FragmentManager manager = getSupportFragmentManager();
if(manager.getBackStackEntryCount()> 0)
{
boolean fragmentPopped = manager.popBackStackImmediate(backStateName, 0);
if (!fragmentPopped && manager.findFragmentByTag(backStateName) == null) {
//fragment not in back stack, create it.
addFragment(fragment, manager, backStateName);
}
}
else // no fragments
{
addFragment(fragment, manager, backStateName);
}
}
public void addFragment(Fragment fragment, FragmentManager manager, String backStateName)
{
FragmentTransaction ft = manager.beginTransaction();
ft.replace(R.id.container, fragment, backStateName);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.addToBackStack(backStateName);
ft.commit();
}
public void clearBackStack() {
getSupportFragmentManager().popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
И при нажатии на элемент меню ящика
@Override
public boolean onNavigationItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.nav_camera) {
addFragmentFromMenu(CameraFragment.newInstance("cam1", "cam2"));
} else if (id == R.id.nav_gallery) {
addFragmentFromMenu(TestFragment.newInstance("test1","test2"));
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
Ответ 5
Я сделал следующий путь. Очистите весь фрагмент, затем добавьте первый фрагмент дома
FragmentManager fm = getActivity().getSupportFragmentManager();
fm.popBackStack(Constants.TAG_HOME, FragmentManager.POP_BACK_STACK_INCLUSIVE);
((MainActivity) activity).manageFragment(new HomeFragment(), Constants.TAG_HOME);
// write down below function in main activity
public void manageFragment(Fragment fragment, String tag) {
FragmentManager fragmentManager = getSupportFragmentManager();
if (!fragmentManager.popBackStackImmediate(tag, 0)) {
FragmentTransaction ft = fragmentManager.beginTransaction();
ft.add(R.id.content_frame, fragment, tag);
ft.addToBackStack(tag);
ft.commit();
}
}
Ответ 6
1) Добавьте первый фрагмент, используя приведенный ниже код
android.support.v4.app.FragmentManager fm = getActivity().getSupportFragmentManager();
android.support.v4.app.FragmentTransaction ft=fm.beginTransaction();
if (fm.findFragmentById(R.id.fragment_container) != null) {
ft.hide(fm.findFragmentById(R.id.fragment_container));
}
ft.add(R.id.fragment_container, new OneFragment(),OneFragment.class.getCanonicalName())
.addToBackStack(OneFragment.class.getCanonicalName()).commit();
2) Добавьте второй фрагмент из первого фрагмента, используя приведенный ниже код
android.support.v4.app.FragmentManager fm = getActivity().getSupportFragmentManager();
android.support.v4.app.FragmentTransaction ft=fm.beginTransaction();
if (fm.findFragmentById(R.id.fragment_container) != null) {
ft.hide(fm.findFragmentById(R.id.fragment_container));
}
ft.add(R.id.fragment_container,new TwoFragment(),TwoFragment.class.getCanonicalName())
.addToBackStack(TwoFragment.class.getCanonicalName()).commit();
3) Добавьте третий фрагмент из второго фрагмента, используя приведенный ниже код
android.support.v4.app.FragmentManager fm = getActivity().getSupportFragmentManager();
android.support.v4.app.FragmentTransaction ft=fm.beginTransaction();
if (fm.findFragmentById(R.id.fragment_container) != null) {
ft.hide(fm.findFragmentById(R.id.fragment_container));
}
ft.add(R.id.fragment_container, new ThreeFragment(),ThreeFragment.class.getCanonicalName())
.addToBackStack(ThreeFragment.class.getCanonicalName()).commit();
4) Добавьте фрагмент Forth из третьего фрагмента, используя приведенный ниже код
android.support.v4.app.FragmentManager fm = getActivity().getSupportFragmentManager();
android.support.v4.app.FragmentTransaction ft=fm.beginTransaction();
if (fm.findFragmentById(R.id.fragment_container) != null) {
ft.hide(fm.findFragmentById(R.id.fragment_container));
}
ft.add(R.id.fragment_container, new FourFragment(),ThreeFragment.class.getCanonicalName())
.addToBackStack(FourFragment.class.getCanonicalName()).commit();
5) onBackPressed(), пожалуйста, напишите ниже код
@Override
public void onBackPressed() {
hideKeyboard(MainActivity.this);
Fragment currentFragment = this.getSupportFragmentManager().findFragmentById(R.id.fragment_container);
if (currentFragment.getClass().getName().equalsIgnoreCase(FourFragment.class.getName())) { // Using this code come from third fragment to first fragment
Fragment f = this.getSupportFragmentManager().findFragmentByTag(TwoFragment.class.getCanonicalName());
if (f != null) {
this.getSupportFragmentManager().popBackStackImmediate(f.getClass().getCanonicalName(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
}else {
super.onBackPressed();
}
}
Ответ 7
Просмотрев много постов, я понял это следующим образом:
в методе fragC => fragD выполните две транзакции:
1 чистая стека, fragC => fragA
2 fragA => fragD
Но при этом исходное состояние fragA может быть разрушено.
public static void changeFragCtoD(FragmentManager fm, Fragment fragD){
fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
FragmentTransaction fragmentTransaction = fm.beginTransaction();
fragmentTransaction
.replace(R.id.containerViewId, new fragAClass())
.commit();
FragmentTransaction fragmentTransaction = fm.beginTransaction();
fragmentTransaction
.replace(R.id.containerViewId, fragD)
.addToBackStack(fragD.getClass().getName())
.commit();
}
Теперь нажатие на fragD возвращает к fragA.
Ответ 8
Помните мои слова, завершенный FragmentTransaction
добавляется в backstack, а не просто в фрагмент, значит, даже если вы добавляете и удаляете фрагмент в одной транзакции, вызывая poBackStack()
, сторнирует полную транзакцию. Передача тега в его аргументе выводит всю транзакцию до помеченной транзакции или даже отображает помеченную транзакцию (в случае, если FragmentManager.POP_BACK_STACK_INCLUSIVE
добавлен к аргументу)
Так что это больше о том, как вы его добавили, а не о том, как вы его удалили.
Смотрите Выполнение транзакций с фрагментами