Shy*_*ine 30 android android-navigation android-jetpack android-architecture-navigation
基本上,我有以下导航图:
我希望fragment 2在到达之后将导航图中的起点更改为正确(为了防止fragment 1在按下后退按钮时返回 - 就像启动画面一样).
这是我的代码:
navGraph = navController.getGraph();
navGraph.setStartDestination(R.id.fragment2);
navController.setGraph(navGraph);
Run Code Online (Sandbox Code Playgroud)
但是,显然它不起作用,fragment 1按下后退按钮后又回来了.
我做错了吗?还有其他解决方案吗?
Ale*_*nko 35
如果您有这样的导航图:
<fragment
android:id="@+id/firstFragment"
android:name="com.appname.package.FirstFragment" >
<action
android:id="@+id/action_firstFragment_to_secondFragment"
app:destination="@id/secondFragment" />
</fragment>
<fragment
android:id="@+id/secondFragment"
android:name="com.appname.package.SecondFragment"/>
Run Code Online (Sandbox Code Playgroud)
并且您希望导航到第二个片段并将其作为图形的根,指定下一个NavOptions:
NavOptions navOptions = new NavOptions.Builder()
.setPopUpTo(R.id.firstFragment, true)
.build();
Run Code Online (Sandbox Code Playgroud)
并使用它们进行导航:
Navigation.findNavController(view).navigate(R.id.action_firstFragment_to_secondFragment, bundle, navOptions);
Run Code Online (Sandbox Code Playgroud)
setPopUpTo(int destinationId, boolean inclusive)- 在导航之前弹出到指定目的地.这将从后堆栈中弹出所有不匹配的目标,直到找到此目标.
destinationId- 弹出目的地,清除所有干预目的地.
inclusive- 如果从后栈中弹出给定目标,则为true.
不推荐使用:已弃用操作的clearTask属性和关联的API NavOptions.
资料来源:https://developer.android.com/jetpack/docs/release-notes
如果您想要将根片段更改为fragment 2(例如,按下后退按钮,fragment 2您将退出应用程序),您应该将下一个属性添加到您的action或destination:
<fragment
android:id="@+id/firstFragment"
android:name="com.appname.package.FirstFragment" >
<action
android:id="@+id/action_firstFragment_to_secondFragment"
app:destination="@id/secondFragment"
app:popUpTo="@+id/firstFragment"
app:popUpToInclusive="true" />
</fragment>
<fragment
android:id="@+id/secondFragment"
android:name="com.appname.package.SecondFragment"/>
Run Code Online (Sandbox Code Playgroud)
实际上它看起来是另一种方式:
findNavController(fragment).navigate(
FirstFragmentDirections.actionFirstFragmentToSecondFragment())
Run Code Online (Sandbox Code Playgroud)
我加入app:clearTask="true"了行动.
现在当您执行导航fragment 1时fragment 2使用下一个代码:
app:clearTask="true"
Run Code Online (Sandbox Code Playgroud)
sza*_*ske 16
我为此找到了解决方案,但它很难看。我想这是一个 alpha 库可以预期的,但我希望谷歌考虑简化/修复这个问题,因为这是一个非常流行的导航模式。
Alexey 的解决方案对我不起作用。我的问题是我的操作栏上显示了向上箭头,方法是使用:
NavigationUI.setupActionBarWithNavController(this, navController)
如果我按照上面 Alexey 的建议去做,我的新开始片段仍然有一个箭头指向我的初始开始片段。如果我按下向上箭头,我的应用程序将重新启动,过渡到自身(新的开始片段)
这是获得我想要的代码所需的代码:
这是完成此操作的代码。在我的活动的 onCreate 中:
// Setup the toolbar
val toolbar = findViewById<Toolbar>(R.id.toolbar)
setSupportActionBar(toolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(false)
// Configure the navigation
val navHost = nav_host_fragment as NavHostFragment
graph = navHost.navController
.navInflater.inflate(R.navigation.nav_graph)
graph.startDestination = R.id.welcomeFragment
// This seems to be a magical command. Not sure why it's needed :(
navHost.navController.graph = graph
NavigationUI.setupActionBarWithNavController(this, navHost.navController)
Run Code Online (Sandbox Code Playgroud)
并且:
fun makeHomeStart(){
graph.startDestination = R.id.homeFragment
}
Run Code Online (Sandbox Code Playgroud)
然后在片段 #1 的 onActivityCreated 中,根据 Alexey 的建议:
override fun onActivityCreated(savedInstanceState: Bundle?) {
...
// Check for user authentication
if(sharedViewModel.isUserAuthenticated()) {
(activity as MainActivity).makeHomeStart() //<---- THIS is the key
val navOptions = NavOptions.Builder()
.setPopUpTo(R.id.welcomeFragment, true)
.build()
navController.navigate(R.id.action_welcomeFragment_to_homeFragment,null,navOptions)
} else {
navController.navigate(R.id.action_welcomeFragment_to_loginFragment)
}
}
Run Code Online (Sandbox Code Playgroud)
关键代码是:
(activity as MainActivity).makeHomeStart()它只是在活动中运行一个方法来改变图表 startDestination。我可以清理它并将其变成一个界面,但我会等待谷歌并希望他们改进整个过程。方法“setPopUpTo”对我来说似乎命名不佳,并且命名从图形中切出的片段并不直观。他们在 navOptions 中进行这些更改对我来说也很奇怪。我认为 navOptions 只会与它们连接的导航操作有关。
我什至不知道是什么navHost.navController.graph = graph,但没有它向上箭头返回。:(
我正在使用导航 1.0.0-alpha06。
Doc*_*ger 13
您也可以尝试以下方法。
val navController = findNavController(R.id.nav_host_fragment)
if (condition) {
navController.setGraph(R.navigation.nav_graph_first)
} else {
navController.setGraph(R.navigation.nav_graph_second)
}
Run Code Online (Sandbox Code Playgroud)
与其尝试弹出开始目的地或手动导航到目标目的地,不如拥有另一个具有不同工作流程的导航图。当您有条件地想要完全不同的导航流程时,这会更好。
在 MainActivity.kt
val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
val inflater = navHostFragment.navController.navInflater
val graph = inflater.inflate(R.navigation.booking_navigation)
if (isTrue){
graph.startDestination = R.id.DetailsFragment
}else {
graph.startDestination = R.id.OtherDetailsFragment
}
val navController = navHostFragment.navController
navController.setGraph(graph, intent.extras)
Run Code Online (Sandbox Code Playgroud)
从 nav_graph.xml 中删除 startDestination
?xml version="1.0" encoding="utf-8"?>
<!-- app:startDestination="@id/oneFragment" -->
<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/navigation_main">
<fragment
android:id="@+id/DetailFragment"
android:name="DetailFragment"
android:label="fragment_detail"
tools:layout="@layout/fragment_detail"/>
<fragment
android:id="@+id/OtherDetailFragment"
android:name="OtherDetailFragment"
android:label="fragment_other_detail"
tools:layout="@layout/fragment_other_detail"/>
</navigation>
Run Code Online (Sandbox Code Playgroud)
您实际上并不需要弹出 Splash Fragment。它可以在您的应用程序生命周期的剩余时间内保留在那里。您应该做的是从启动屏幕确定下一个要显示的屏幕。
在上图中,您可以在闪屏状态下询问是否有保存的LoginToken。如果为空,则导航到登录屏幕。
登录屏幕完成后,您可以分析结果,保存令牌并导航到下一个片段主屏幕。
当在主屏幕中按下后退按钮时,您将向启动屏幕发送回一条结果消息,指示它完成应用程序。
下面的代码可能有帮助:
val nextDestination = if (loginSuccess) {
R.id.action_Dashboard
} else {
R.id.action_NotAuthorized
}
val options = NavOptions.Builder()
.setPopUpTo(R.id.loginParentFragment, true)
.build()
findNavController().navigate(nextDestination, null, options)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
12410 次 |
| 最近记录: |