基本上,我有以下导航图:
我想在到达它后立即将导航图中的起点改为fragment 2
(为了防止在按下后退按钮时回到fragment 1
- 就像启动画面一样)。
这是我的代码:
navGraph = navController.getGraph();
navGraph.setStartDestination(R.id.fragment2);
navController.setGraph(navGraph);
但是,显然它不起作用,按下后退按钮后它会回到fragment 1
。
我做错了吗?还有其他解决方案吗?
如果您有这样的导航图:
<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"/>
并且您想要导航到第二个片段并使其成为图形的根,指定下一个NavOptions
:
NavOptions navOptions = new NavOptions.Builder()
.setPopUpTo(R.id.firstFragment, true)
.build();
并使用它们进行导航:
Navigation.findNavController(view).navigate(R.id.action_firstFragment_to_secondFragment, bundle, navOptions);
setPopUpTo(int destinationId, boolean inclusive)
- 在导航之前弹出到指定的目的地。这将从后堆栈中弹出所有不匹配的目标,直到找到此目标。
destinationId
- 弹出的目的地,清除所有干预目的地。
inclusive
- 如果从后堆栈中弹出给定目标,则为true。
<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"/>
然后在你的代码上:
findNavController(fragment).navigate(
FirstFragmentDirections.actionFirstFragmentToSecondFragment())
不推荐使用:clearTask
中的操作和关联API的NavOptions
属性已被弃用。
资料来源:https://developer.android.com/jetpack/docs/release-notes
如果你想将你的根片段更改为fragment 2
(例如,在fragment 2
上按回按钮后你将退出应用程序),你应该将下一个属性放到你的action
或destination
:
app:clearTask="true"
实际上它看起来是另一种方式:
<fragment
android:id="@+id/firstFragment"
android:name="com.appname.package.FirstFragment"
android:label="fragment_first" >
<action
android:id="@+id/action_firstFragment_to_secondFragment"
app:destination="@id/secondFragment"
app:clearTask="true" />
</fragment>
<fragment
android:id="@+id/secondFragment"
android:name="com.appname.package.SecondFragment"
android:label="fragment_second"/>
我已经添加了app:clearTask="true"
来行动。
现在,当您执行从fragment 1
到fragment 2
的导航时,请使用下一个代码:
Navigation.findNavController(view)
.navigate(R.id.action_firstFragment_to_secondFragment);
我找到了解决方案,但它很难看。我想这可以用alpha库来预料,但我希望谷歌考虑简化/修复它,因为这是一个非常流行的导航模式。
阿列克谢的解决方案对我不起作用。我的问题是我使用以下方法在我的Actionbar上显示箭头:
NavigationUI.setupActionBarWithNavController(this, navController)
如果我按照Alexey的建议,我的新起始片段仍然有一个箭头指向我的初始起始片段。如果我按下向上箭头我的应用程序将重新启动,转换为自身(新的开始片段)
这是获得我想要的代码所需的代码:
这是完成此任务的代码。在我的Activity's 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)
并且:
fun makeHomeStart(){
graph.startDestination = R.id.homeFragment
}
然后在片段#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)
}
}
关键代码是:(activity as MainActivity).makeHomeStart()
,它只是在活动中运行一个方法来更改图形startDestination。我可以将其清理干净并将其转换为界面,但我会等待Google并希望他们改进整个过程。方法'setPopUpTo'似乎对我的命名很差,并且你命名从图中删除的片段并不直观。对我来说,他们在navOptions中进行这些更改也很奇怪。我认为navOptions只与他们所连接的导航动作有关。
我甚至不知道navHost.navController.graph = graph
做了什么,但没有它,向上箭头返回。 :(
我正在使用Navigation 1.0.0-alpha06。