我正在处理碎片事务,并且返回栈是这样的:
fragA => fragB => fragC => fragD
我希望从fragD返回fragA
fragD => onBackPress => fragA
所以,我尝试了这样的代码:
getChildFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
但它清除了整个后退栈,我该如何保留第一个片段在后退栈中?非常感谢。
我正在处理碎片事务,并且返回栈是这样的:
fragA => fragB => fragC => fragD
我希望从fragD返回fragA
fragD => onBackPress => fragA
所以,我尝试了这样的代码:
getChildFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
但它清除了整个后退栈,我该如何保留第一个片段在后退栈中?非常感谢。
例如,你可以执行以下操作:
P.S. 还有其他方法可以实现你想要的内容。这取决于...
fragmentTransaction.add(new FragmentA(), "FragmentA_Tag");
当用户按下后退按钮时,您可以稍后确定要显示哪个片段...
FragmentA f = fragmentManager.findFragmentByTag("FragmentA_Tag");
if(f != null){
f.show();
}
Fragment
类的isHidden
方法...顺便说一下,我在这里谈论的是原生片段,而不是支持库的片段。后退栈包含有关事务的记录,而不是片段本身。
因此,您不应将第一个事务的记录(null -> fragA)添加到后退栈中。
所有其他事务的记录都应添加到后退栈中。
在这种情况下,当您执行popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
时,Android会除了fragA之外所有片段,因为没有任何记录说明如何添加fragA。
我最近开始学习Android中的碎片(Fragment),也遇到了这个问题。在这里,我展示了我的解决方案以及如何解决这个问题。如果我的代码有误,请修正。我们现在有什么?一个Activity,许多Fragment和它们的后退栈。我们想要从抽屉菜单中打开每个Fragment并清除后退栈中的所有其他Fragment。但是,我们必须只保留一个Home Fragment。当我们停留在Home Fragment时,用户按下返回按钮应用程序将关闭。
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;
}
在查看了许多帖子后,我找到了这种方法:
在 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();
}
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();
}
}
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) 使用以下代码从第三个片段添加第四个片段
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();
}
}
记住我的话,完整的FragmentTransaction
被添加到后退栈中,不仅仅是一个片段,这意味着即使您在单个事务中添加和删除片段,调用poBackStack()
也会反转完整的事务。在其参数中传递标记会弹出所有事务,直到标记的事务,甚至弹出标记的事务(如果将FragmentManager.POP_BACK_STACK_INCLUSIVE
添加到参数中)
因此,更多的是关于您如何添加它而不是如何删除它。
请参见执行片段事务。
我知道这已经晚了,对于你的问题回答来说,但它可能对其他人有所帮助。
因为我过去几天一直在寻找解决方案... 我用 for 循环解决了它,我认为这是最简单的方法。
首先,以这种方式初始化一个整数
int count = getSupportFragmentManager().getBackStackEntryCount();
其中getBackStackEntryCount()将计算事务的数量。
然后在调用fragD中的FragmentTransaction方法之前,添加此for循环。
for (int i = 0; i < count; i++){
getSupportFragmentManager().popBackStack();
}
for循环可以为您完成任务,而popBackStack()将使您返回到fragA
它看起来像这样
int count = getSupportFragmentManager().getBackStackEntryCount();
for (int i = 0; i < count; i++){
getSupportFragmentManager().popBackStack();
}
fragmentTransaction.replace(R.id.frame_layout, new FoodFragment(), "Food").addToBackStack(null);
fragmentTransaction.commit();
@Override
public void onBackPressed() {
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
if (!(getSupportFragmentManager().getBackStackEntryCount() == 1)) {
getSupportFragmentManager().popBackStack() ;
}
}
}