使用导航控制器按下后退按钮后如何防止前一个片段显示?

Posted

技术标签:

【中文标题】使用导航控制器按下后退按钮后如何防止前一个片段显示?【英文标题】:How to prevent previous fragment to show up after pressing back button using navigation controller? 【发布时间】:2019-07-21 23:30:23 【问题描述】:

我现在正在尝试使用导航控制器。我想从LoginFragment 移动到HomeFragment。在LoginFragment 中,我使用下面的代码移动到HomeFragment

Navigation.findNavController(view).navigate(homeDestination)

但是,当我点击HomeFragment 中的返回按钮时,它会回到LoginFragment,我希望当我点击该按钮时它会关闭应用程序。

以旧的方式,如果我使用活动而不是使用Fragment,我通常会做这样的事情来获得预期的行为:

val intent = Intent(this,HomeActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK.or(Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(intent)

通过使用这些标志,我可以得到预期的行为。但我不知道如何使用导航控制器实现相同的行为。

【问题讨论】:

当您尝试从以前创建新片段时,请使用替换代替添加。 getSupportFragmentManager().beginTransaction() .replace(R.id.container_between, policies, Policies.TAG) .addToBackStack(Policies.TAG).commit(); @Shane - 使用 Navigation 时不要直接使用 FragmentTransactions。 @Shane 我正在使用安卓导航组件,不再使用片段事务developer.android.com/topic/libraries/architecture/navigation/… 请注意,根据Principles of Navigation 和conditional navigation documentation,您不应该使用登录片段作为您的起始目的地。 【参考方案1】:

导航提供了popUpTopopUpToInclusive 属性,用于在navigate() 操作中从后台堆栈中删除片段。

这可以在 XML 中设置:

<!-- Add to your Navigation XML, then use navigate(R.id.go_home) -->
<action
  android:id="@+id/go_home"
  app:destination="@+id/home_fragment"
  app:popUpTo="@+id/destination_to_pop"
  app:popUpToInclusive="true"/>

或以编程方式设置:

NavOptions navOptions = new NavOptions.Builder()
    .setPopUpTo(R.id.destination_to_pop, true)
    .build();
Navigation.findNavController(view).navigate(homeDestination, navOptions)

您也可以使用 &lt;navigation&gt; 元素的 id。

【讨论】:

【参考方案2】:

我一直在关注 Ian 的回答,但我一直运气不好,因为我不知道 popUpTo 会是什么。

所以我们必须在那里使用 nav Graph 的 id。

app:popUpTo="@+id/idOfNavGraph". //id of nav graph

<action
  android:id="@+id/go_home"
  app:destination="@+id/home_fragment"
  app:popUpTo="@+id/idOfNavGraph". //id of nav graph
  app:popUpToInclusive="true"/>

【讨论】:

【参考方案3】:

我认为这应该可以解决问题。

NavController controller = Navigation.findNavController(view);
controller.popBackStack(R.id.fragmentLogin, true);
controller.navigate(homeDestination)

【讨论】:

虽然这在某种程度上有效,但 Navigation 提供了一个内置的 popUpTo 属性,将其作为单个操作执行,而无需针对该中间状态向 OnDestinationChangedListener 发送更新。 是的。这是正确的想法。我看到你的答案后来我发布了我的。你的完美。赞一个!【参考方案4】:

试试这个

 val c = view.findNavController()
 c.popBackStack() // current fragment will be pop up from the stack
 c.navigate(DestinationFragmentID)

【讨论】:

【参考方案5】:

显然我迟到了。尽管如此,我还是想尽我所能并扩展伊恩的答案。在app:popUpTo="@+id/destination_to_pop" 中,destination_to_pop 确实意味着您不想保留在后堆栈中的目的地。在你的情况下,loging_fragment

这样,当您从HomeFragment 导航回来时,应用程序将关闭,因为LoginFragment 不再在后台堆栈中。你可以找到相关的官方文档here。

【讨论】:

以上是关于使用导航控制器按下后退按钮后如何防止前一个片段显示?的主要内容,如果未能解决你的问题,请参考以下文章

如何防止在android片段中按下后退按钮时调用onCreateView

覆盖ios后退按钮

如何检测在导航控制器的下一个视图控制器中按下后退按钮

如何确定后退按钮按下

按下视图控制器后删除“返回”按钮

按下后退按钮后,从另一个视图控制器更改按钮