17

我正在处理片段事务,backstack是这样的:

fragA => fragB => fragC => fragD

从 fragD 回来后,我想回到 fragA

fragD => onBackPress => fragA

所以,我尝试了如下代码:

getChildFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);

但它清除了所有的 backstack ,我怎样才能将第一个片段保留在 backstack 中?非常感谢

4

10 回答 10

24

例如,您可以执行以下操作:

  • 添加 fragA 而不将其添加到 backStack。因此它始终处于
    活动状态,并且不会对后退按钮做出反应。
  • 当您打开 fragD 时,您应该清除片段 BackStack。因此,当您按下 D 片段的后退按钮时,您将返回 A。

PS还有其他方法可以做你想做的事。这取决于...

于 2015-02-06T08:33:05.480 回答
4

因为“后栈”具有类似栈的行为……后进先出……添加到后栈的最后一个片段将首先从后栈中弹出。您将需要通过指定您自己的来手动实现所需的行为。FragmentManager使用类方法并不难。

如果您在将片段添加到事务时“标记”它们......

 fragmentTransaction.add(new FragmentA(), "FragmentA_Tag");

您可以稍后确定按下后退按钮时要显示哪个片段...

FragmentA f = fragmentManager.findFragmentByTag("FragmentA_Tag");
if(f != null){
    f.show();
}

如何确定显示哪个片段完全取决于您。您可以跟踪当前可见的片段,也可以使用类的isHidden方法Fragment......顺便说一句,我在这里谈论的是原生片段,不支持库的片段。

于 2015-02-06T08:06:11.070 回答
4

backstack 包含有关事务的记录,而不是片段本身。所以你不应该将第一笔交易的记录(null -> fragA)添加到后台堆栈。并且所有其他交易的记录都应该添加到 backstack 中。在这种情况下,然后你 preform popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);android 删除了除 fragA 之外的所有片段,因为没有任何关于如何添加 fragA 的记录。

于 2015-02-06T08:22:31.890 回答
2

就在几天前,我开始学习 Android 中的片段。我也遇到了这个问题。在这里,我展示了我的解决方案以及我如何解决这个问题。如果我的代码不正确,请修复。这个时候我们有什么?活动,许多片段和他们的后台。我们希望从 Drawer 菜单中打开每个片段,并从 backstack 中清除所有其他片段。但是,我们必须只持有一个 Home 片段。当我们停留在主页片段并且用户按下返回按钮时,应用程序正在关闭。

活动类

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;
}
于 2017-01-29T17:34:08.097 回答
1

看了很多帖子后,我是这样想的:

在 fragC => fragD 方法中,做两个事务:

1 清除回栈,fragC => fragA

2 碎片A => 碎片D

但这样一来,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。

于 2019-09-18T10:41:38.790 回答
0

我已经完成了以下方式。清除所有片段,然后添加第一个主片段

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();

            }
        }
于 2017-08-18T17:16:49.967 回答
0

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();
        }
    }
于 2018-08-24T18:39:51.297 回答
0

记下我的话,completeFragmentTransaction被添加到 backstack 而不仅仅是一个片段,这意味着即使你在单个事务调用中添加和删除片段poBackStack()也会反转完整的事务。在其参数中传递一个标签会弹出所有事务直到标记的事务,甚至弹出标记的事务(如果FragmentManager.POP_BACK_STACK_INCLUSIVE添加到参数中)因此更多的是关于如何添加它而不是如何删除它。请参阅执行片段事务

于 2019-10-03T11:14:15.733 回答
0

我知道现在回答您的问题为时已晚,但这可能对其他人有帮助。由于过去几天我一直在寻找解决方案......我已经使用 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();
于 2020-04-22T09:58:44.677 回答
0

您覆盖 onbackpressed (Mainactivity) 并使用片段管理器的 getBackStackEntryCount(),您可以检查它是否不等于 1 并仅在该条件下弹出回栈。

@Override
public void onBackPressed() {
  if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
     if (!(getSupportFragmentManager().getBackStackEntryCount() == 1)) {
      getSupportFragmentManager().popBackStack() ;
    }
  }    
}

于 2020-08-22T03:13:15.733 回答