【问题标题】:Android BackStack NavigationDrawerAndroid BackStack NavigationDrawer
【发布时间】:2015-01-21 16:41:09
【问题描述】:

过去几天我一直在处理一个问题,但似乎没有找到答案。

描述:我有一个包含导航抽屉的主要活动。导航抽屉的每个项目(单击时)都会创建一个片段。在该片段中,有一个对象列表视图,单击时会创建其他片段。在这些片段中,我有另一个打开其他片段的对象列表视图。换句话说,有一系列片段打开其他片段。像这样的:

http://s22.postimg.org/pddo5gsv5/backstack.png

为了能够返回到每个片段,我实现了 addToBackstack("string") 方法。

我的问题是,我怎样才能为我的应用程序实现正确的后台堆栈,以便当我单击导航抽屉项时,已添加到后台堆栈的所有片段都被清除,而导航抽屉项打开的片段没有。

任何帮助将不胜感激。谢谢!

编辑

好的,看来我设法弄明白了。考虑到我从回复中收到的建议,这是我想出的解决方案:

@Override
public void onBackPressed() {
    int count = getFragmentManager().getBackStackEntryCount();
    if (count != 0) {
        FragmentManager.BackStackEntry backEntry = getFragmentManager()
                .getBackStackEntryAt(
                        getFragmentManager().getBackStackEntryCount() - 1);
        if (backEntry.getName() == NAVIGATION) {
            finish();
        } else
            getFragmentManager().popBackStack();
    } else {
        super.onBackPressed();
    }
}

简而言之:首先,我添加了一个 backstack 条目,即使是顶级片段,也给它们一个特定的标签。我已经覆盖了 Activity 的后退按钮功能,以便当最后一个 backstack 条目是完成活动的顶级片段时(这样它就不会简单地将片段从活动中分离出来,而是将其保持为空)。否则,如果最后一个条目不是顶级片段,则执行 popBackStack。 PS:所有非顶级片段都使用与顶级标签不同的标签添加到后台堆栈。此外,我必须在导航抽屉的点击监听器中执行 POP_BACK_STACK_INCLUSIVE。

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

感谢大家的建议,希望此 EDIT 对其他用户有所帮助。

【问题讨论】:

  • 我越来越多地使用抽屉布局,我认为iosched 示例应用程序做得最好。多个活动都有自己的内容片段和自己的带有预选部分的抽屉,因此您只使用活动堆栈而不必担心片段堆栈。 “这是我对你的智慧。”

标签: android listview android-fragments navigation-drawer back-stack


【解决方案1】:

您可以使用以下代码来解决您的问题:

getFragmentManager().beginTransaction()
                    .replace(R.id.fragment_container, fragment)
                    .addToBackStack(fragment_tag)
                    .commit();

为了使上面的代码工作,你必须动态地创建片段。因为无法替换硬编码片段。为此,您可以创建一个容器(FrameLayout 等),在我们的示例中,该容器的 id 为 fragment_container。然后,上面的代码将在容器中动态添加片段。最后,您必须在 addToBackStack 方法中将 fragment_tag 作为参数传递。这意味着,该交易将被添加到后台堆栈中。最后,为了从后台获取它,您必须使用以下代码:

getFragmentManager().popBackStack(fragment_tag, FragmentManager.POP_BACK_STACK_INCLUSIVE));

POP_BACK_STACK_INCLUSIVE 标志确保“所有匹配的条目都将被消耗,直到找到不匹配的条目或到达堆栈底部。否则,将删除直到但不包括该条目的所有条目。”

【讨论】:

  • 动态创建片段到底是什么意思?我创建片段的方式是制作它们的 xml 布局,然后在 java 代码中对它们进行扩展。之后,我使用 .add 和 .replace 方法将它们添加到活动中。我使用你上面写的确切方法,但是,在我的导航抽屉监听器的 onClick 按钮上,我想从后台堆栈中弹出的片段的某些元素上出现一些空指针异常。
  • @Phantom 我的意思是您不能替换静态放置在 xml 布局文件中的片段。您需要以编程方式创建它们。
  • 但这难道不违反Android Fundamentals,必须通过代码创建片段的布局吗?我知道这是可以做到的,但是这种方式更难,也更耗时。此外,我使用 xml 文件静态创建片段,并且可以毫无问题地替换它们。我唯一的问题是,当我尝试从导航抽屉单击侦听器的后台堆栈中删除它们时,我从它们那里得到空指针异常,我不知道为什么,因为我不想访问它们,我只想从后台删除
  • @Phantom 我不会说它违反了 android 的基本原理,因为我同意维护它更难。使用 addToBackStack(null) 并且不要传递任何标签。我认为这可行。
  • 可悲的是,这不是因为我已经尝试过了。显示了来自片段中某些元素的空指针异常的相同错误。而且,我也不知道为什么,因为我不访问这些片段。
【解决方案2】:

您可以使用类似以下的方式清除片段回栈:

fragmentManager.popBackStack("string", FragmentManager.POP_BACK_STACK_INCLUSIVE);

然后你可以像往常一样addToBackstackcommitMore info.

一个代码 sn-p 显示了我通常在导航抽屉中使用它的方式:

FragmentManager fragmentManager = getSupportFragmentManager();
if(clearBackStack) {
    fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
FragmentTransaction ft = fragmentManager.beginTransaction();
ft.replace(R.id.content_frame, fragment);
if(!clearBackStack) {
    ft.addToBackStack(null);
}
ft.commit();

【讨论】:

  • 这正是我目前使用的方法(我在后台堆栈中添加了所有具有相同字符串的片段)。我应该把这个功能放在哪里?因为它现在在哪里(在 DrawerItemClicklListener 中,我从我想从后台弹出的片段的某些元素中获得空指针异常
  • 添加了一个例子,它可以放在你的监听器中。 NullPointerExceptions 可能与其他问题有关,您可以仔细检查您的片段生命周期。
  • 当导航抽屉中的元素被点击时,我将其设置为 true 表示我们正在访问一个新的“顶级”片段(您提供的图片中的第一个片段列)。否则设置为 false 以将片段添加到当前 backstack。
  • 我刚刚意识到,您不希望 addToBackstack 用于顶级片段。我正在修改示例,很抱歉造成混淆。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-12-30
  • 2014-03-07
  • 1970-01-01
  • 1970-01-01
  • 2014-09-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多