【问题标题】:Android Navigation Component - How to "popBackStack" to non-existing DestinationAndroid导航组件 - 如何“popBackStack”到不存在的目的地
【发布时间】:2020-10-21 05:54:32
【问题描述】:

我的应用程序中的默认路由是 - Auth -> Main -> Chat。但有时我需要使用另一条路线:Auth -> Details -> Chat。当我按下后退按钮(在这两种情况下)时,我想导航到Main 屏幕,但在第二种情况下它不在后台堆栈中。我尝试创建Global-action 以使用popUpTo == MainDetails 屏幕导航到Chat

<action
    android:id="@+id/action_global_to_chat"
    app:destination="@id/navigation_chat"
    app:launchSingleTop="true"
    app:popUpTo="@id/navigation_main_host" />

但它不起作用,因为navigation_main_host 不在后台堆栈中。有没有办法得到这种行为?

UPD:我尝试了另一种解决方案 - 我在 Chat 目标中创建了另一个动作,其行为为 popup inclusive

    <action
        android:id="@+id/action_chat_to_main_host"
        app:destination="@id/navigation_main_host"
        app:popUpTo="@id/navigation_auth"
        app:popUpToInclusive="true" />

然后我尝试在我的ChatFragment 中使用它:

private val backPressedCallback = object : OnBackPressedCallback(true) {
    override fun handleOnBackPressed() {
        if (activityController?.getNavController()?.previousBackStackEntry?.destination?.id == R.id.navigation_main_host) {
            activityController?.getNavController()?.popBackStack()
        } else {
            activityController?.getNavController()?.navigate(ChatDirections.actionChatToMainHost())
        }
    }
}

但是当我尝试它时,我得到了这条路线:

Auth -&gt; Details -&gt; Chat

然后我开始按下返回按钮:

Chat -&gt; Main -&gt; Chat -&gt; Main -&gt; Chat -&gt; Main....在无限循环中。

backPressedCallbackonResume 中启用,在onPause 中禁用以明确说明。

【问题讨论】:

  • @Abhimanyu 你到底想在这个页面上给我看什么?我已阅读,但我的问题没有答案。
  • 我认为这是您的用例。如果我遗漏了什么,请告诉我。您希望您的应用程序处理打开特定屏幕(聊天屏幕)的意图。当用户按下后退按钮时,他们会向后导航导航堆栈,就像他们从入口点进入您的应用一样。
  • @Abhimanyu 我编辑了我的问题并删除了令人困惑的部分。请看一看。
  • 要确认,一旦你在“聊天”屏幕上,按回应该总是导航到“主”屏幕?

标签: android navigation back-stack


【解决方案1】:

我有一个类似的用例。分享我的实现。希望它对你有用。

在 MainActivity 中:

// Navigation component global variables
private lateinit var navController: NavController
private lateinit var navGraph: NavGraph

// In onCreate()
// fragment_activitymain is a <fragment>
navController = findNavController(R.id.fragment_activitymain)
navGraph = navController.navInflater.inflate(R.navigation.navigation)

private fun setStartDestination(startDestination: Int) {
    navGraph.startDestination = startDestination
    navController.graph = navGraph
}

调用setStartDestination()方法:

setStartDestination(R.id.MainFragmentIdInNavigationGraph)

Activity 中的方法 setStartDestination() 可以从任何 Fragment 调用,方法是使用接口或 livedatashared ViewModel 或在您的应用中实现 Fragment 到 Activity 通信的任何其他方式。

要获得所需的流程,请覆盖“聊天”中的后按并使用操作从“聊天”导航到“主要”,而不是从后台弹出目的地。将“Main”设置为起始目的地会清除 main 下面的目的地。

流程是这样的, 路线一: Auth -> Main -> Chat -> 使用操作导航到 main 并将其设置为启动方法以从 backstack 中清除“Chat”和“Main”。当您在 Auth to Main 操作中使用 popUp 时,“Auth”不会在后台堆栈中。

路线 2: Auth -> Details -> Chat -> 使用操作导航到 main 并将其设置为启动方法以从 backstack 中清除“Chat”和“Details”。如果您在 Auth to Details 操作中使用 popUp,则“Auth”不会在后台堆栈中,否则它将在后台堆栈中,当我们更改起始目的地时也会被清除。

【讨论】:

    【解决方案2】:

    有点老套,但你可以试试:

    private val backPressedCallback = object : OnBackPressedCallback(true) {
        override fun handleOnBackPressed() {
            if (activityController?.getNavController()?.previousBackStackEntry?.destination?.id == R.id.navigation_main_host) {
                activityController?.getNavController()?.popBackStack()
            } else {
                activityController?.getNavController()?.popBackStack(R.id.navigation_auth, true)
                activityController?.getNavController()?.navigate(ChatDirections.actionChatToMainHost())
            }
        }
    }
    

    R.id.navigation_auth 更改为Auth 的ID。

    这会导致:

    Auth -&gt; Details -&gt; Chat 备份到
    Auth -&gt; Main

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-20
      • 1970-01-01
      • 1970-01-01
      • 2021-08-01
      相关资源
      最近更新 更多