如何使用新的导航架构组件在导航中禁用某些片段?

时间:2018-05-14 17:42:26

标签: android android-architecture-components

我正在尝试新的Navigation Architecture Component,我无法弄清楚如何执行此操作:

我有1个活动(MainActivity)+ 3个碎片:

  • SplashFragment(Home)
  • MainFragment
  • SignUpFragment

我想使用SplashFragment来确定我是否应该导航到MainFragment或SignUpFragment,但是一旦它到达那两个中的任何一个,你就不应该回弹到SplashFragment。我怎么能用新的导航组件做到这一点?

我在调用popBackStack之前和之后尝试navigate(R.id.action_xxx),但它们都没有工作(这是有道理的:在它没有任何东西可以弹出之前;它只是关闭刚添加的片段之后)。这是否意味着唯一的方法是覆盖onBackPress来拦截它并确保navigateUp在这些情况下不会被调用?

谢谢!

6 个答案:

答案 0 :(得分:9)

首先,将app:popUpTo='your_nav_graph_id'app:popUpToInclusive="true"属性添加到操作标签。

<fragment
    android:id="@+id/signInFragment"
    android:name="com.glee.incog2.android.fragment.SignInFragment"
    android:label="fragment_sign_in"
    tools:layout="@layout/fragment_sign_in" >
    <action
        android:id="@+id/action_signInFragment_to_usersFragment"
        app:destination="@id/usersFragment"
        app:launchSingleTop="true"
        app:popUpTo="@+id/main_nav_graph"
        app:popUpToInclusive="true" />
</fragment>

第二,使用上述操作作为参数,导航到目的地。

findNavController(fragment).navigate(SignInFragmentDirections.actionSignInFragmentToUserNameFragment())

注意:如果您使用方法navigate(@IdRes int resId)进行导航,则不会获得理想的结果。因此,我使用了方法navigate(@NonNull NavDirections directions)

答案 1 :(得分:7)

警告:clearTask已弃用,将在以后的版本中删除,不确定解决方案是什么。请立即关注this issue以保持最新

哦,10分钟后终于找到了钥匙:使用clearTask

我所要做的就是将app:clearTask="true"添加到该特定操作,或使用.navigate(R.id.actionXXXX, null, NavOptions.Builder().setClearTask(true).build()),并完成。只需确保将其添加到SplashFragment的所有子项(在本例中为MainFragment和SignUpFragment)。

答案 2 :(得分:5)

这在alpha05版本中对我有用。在操作标记中(在nav_graph.xml文件内部)添加app:popUpTo =“ @ id / nav_graph”。 这里的“ @ id / nav_graph是我的图形的ID或也称为Root。

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/nav_graph"
app:startDestination="@id/startFragment">
.......
<action
android:id="@+id/action_startFragment_to_homeFragment"
app:destination="@id/homeFragment" 
app:popUpTo="@id/nav_graph"/>
.......

您还可以在设计标签中执行此操作:-选择“ SplashFragment”,然后选择要更改的操作,然后为“ Pop To”选择“ root”

答案 3 :(得分:2)

因此,如果您具有启动片段和主片段,并且不想在以下方法的主要片段之后返回到启动片段,则可以实现此目的

<fragment
     android:id="@+id/splashFragment"
     android:name="com.example.youappname.views.SplashFragment"
     android:label="fragment_splash"
     tools:layout="@layout/fragment_splash">
     <action
         android:id="@+id/action_splashFragment_to_mainFragment"
         app:destination="@id/mainFragment"
         app:popUpTo="@id/splashFragment"
         app:popUpToInclusive="true"/>
</fragment>

在您的Kotlin飞溅片段中:

private lateinit var navController: NavController

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
      super.onViewCreated(view, savedInstanceState)

      navController = Navigation.findNavController(view)

}

private fun navigateToMainFrag() {
      navController.navigate(R.id.action_splashFragment_to_mainFragment)
}

现在,当您按下“后退”按钮时,它将关闭应用程序,而不是显示启动屏幕

答案 4 :(得分:1)

对于任何想纯粹通过代码执行此操作的人:

Navigation.findNavController(v)
.navigate(R.id.action_splashFragment_to_userProfileFragment2, null, 
new NavOptions.Builder().setPopUpTo(R.id.splashFragment, true).build())

答案 5 :(得分:0)

示例解决方案是在onBackPressedDispatcher的片段/导航上添加Owner Activity

https://developer.android.com/guide/navigation/navigation-custom-back#implement_custom_back_navigation