从返回栈中移除和添加活动

23
导航抽屉的“跨层级导航后返回系统”部分,他们说:
如果用户从导航抽屉导航到较低层次的屏幕,并且该屏幕有直接父级,则后退堆栈将被重置,并且后退指向目标屏幕的父级。这种后退行为与用户从通知中导航到应用程序时的行为相同。

resetting the back stack

我知道可以通过使用FLAG_ACTIVITY_CLEAR_TOP和FLAG_ACTIVITY_NEW_TASK启动一个活动来重置后堆栈,但是这似乎在这里并不可用,因为它不会为Lower 1.1.1创建后堆栈。
有什么办法可以在启动Lower 1.1.1时从堆栈中删除TopView2,并同时添加TopView1->Lower 1.1后堆栈?考虑到这在导航抽屉文件中提到了,我期望有一个简单的解决方案。

1
我的回答有用吗?你尝试过实现向上导航吗?有什么结果或新问题吗? - IsaacCisneros
似乎很有用 - 我得到了除了意图标志之外还有其他东西可用的想法。我还没有尝试实现它,但我们很快会转向它。答案非常非常长,一个带有摘要的第一句话会很有用。谢谢! - aleb
1个回答

63

EDIT 合成版本:

1)在清单文件中声明应用的层级导航结构。

2)应用的根活动应该在你应用程序层次结构中的 TopViews 之间执行视图切换.*

3)层次结构较低的活动应执行“选择性向上”导航。

*重要提示:当进行水平导航(例如切换选项卡或导航抽屉顶部视图)时,不应将事务添加到后退栈中。


完整描述:

您应该避免在新的导航模式(如导航抽屉)中使用 Intent Flags,原因如下:

  • Intent Flags 实际上并不是一个 API。
  • 某些标志仅在精确组合中起作用。
  • 许多标志对大多数第三方应用程序不相关。
  • 与 activity 的 launchMode 冲突。
  • 文档令人困惑。
  • 实现可能成为试错过程。

相反,使用新的导航 API:

  • Jelly Bean 及以上版本支持本地 Up 导航。
  • 基于在清单文件中为每个 <activity> 指定的分层元数据。
  • 支持库通过 NavUtils 为早期的 Android 版本提供了等效的功能。
  • TaskStackBuilder 提供了用于跨任务导航的其他实用程序。

因此,回答您的问题,一般思路如下:

1) 您需要在清单文件中声明每个活动的逻辑父项,使用 android:parentActivityName 属性(和相应的 <meta-data> 元素),例如:

<application ... >
    ...
    <!-- The main/home activity (it has no parent activity) -->
    <activity
        android:name="com.example.myapp.RootDrawerActivity" ...>
        ...
    </activity>
    <!-- A child of the root activity -->
    <activity
        android:name="com.example.myapp.Lower11 "
        android:label="@string/lower11"
        android:parentActivityName="com.example.myapp.RootDrawerActivity" >
        <!-- Parent activity meta-data to support 4.0 and lower -->
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value="com.example.myapp.RootDrawerActivity" />
    </activity>
    <activity
        android:name="com.example.myapp.Lower111 "
        android:label="@string/lower111"
        android:parentActivityName="com.example.myapp.Lower11" >
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value="com.example.myapp.Lower11" />
    </activity>
</application>

2) 在你的根Activity中,抽屉项目的选择应该通过替换Activity当前片段内容来启动“视图切换”操作。

视图切换遵循与列表或选项卡导航相同的基本策略,即视图切换不会创建导航历史记录。此模式仅应在任务的根Activity中使用,在导航层次结构下进一步向下的活动中保留某种形式的向上导航(在你的情况下是Lower 1.1和Lower 1.1.1)。重要的是,在此处,你不需要从堆栈中删除TopView2,而是要执行视图切换,如前所述,将视图的位置(或片段ID)作为额外参数传递。

在你的根Activity中,像这样做:

@Override
protected void onDrawerItemSelected(int position) {

        // Update the main content by replacing fragments
        CategoryFragment fragment = new CategoryFragment();
        Bundle args = new Bundle();
        args.putInt(RootDrawerActivity.ARG_SORT, position);
        fragment.setArguments(args);

        FragmentManager fragmentManager = getSupportFragmentManager();
        fragmentManager.beginTransaction()
                        .replace(R.id.content_frame, fragment).commit();

        // Update selected item and title, then close the drawer
        setDrawerItemChecked(position, true);
        setTitle(getResources().getStringArray(R.array.drawer_array)[position]);
        closeDrawer();

}

3) 接着在层次结构较低的位置(比如Lower1.1),您应该执行“选择性向上”导航,在此过程中重新创建任务堆栈

选择性向上使用户可以自由跨越应用程序的导航层次结构。 应用程序应该将其视为从不同任务进行向上导航一样处理,使用TaskStackBuilder或类似工具替换当前任务栈(这正是您想要的!)。 在任务的根活动之外,这是唯一应该使用的导航抽屉形式。

@Override
protected void onDrawerItemSelected(int position) {

        TaskStackBuilder.create(this)
                        .addParentStack(RootDrawerActivity.class)
                        .addNextIntent(new Intent(this, RootDrawerActivity.class)
                                        .putExtra(RootDrawerActivity.ARG_SORT, position))
                        .startActivities();

}

参考资料:

http://developer.android.com/training/implementing-navigation/ancestral.html https://speakerdeck.com/jgilfelt/this-way-up-implementing-effective-navigation-on-android


1
这个人应该得到好评。我已经搜索了几个小时,像这样的概述涵盖了整个主题! - danijoo
即使在未来,这也是有用的。感谢您出色的回复。 - doorstuck
1
回答不错,但这对于Android 4.4设备无效。最终我传递了一个布尔值,然后在启动的活动中重写了onBackPressed方法。 - Slickelito
1
@Slickelito 为什么它不能在Android 4.4设备上运行? - aleb
这个答案中提到的speakerdeck链接是绝对必读的!如果你的目标API级别为16及以上,大多数情况下你甚至不需要做任何事情。框架会为你处理一切。 - janakagamini

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接