动态更改 BottomNavigationView 内嵌套导航图的 startDestination
Dynamically change startDestination of nested navigation graph inside of a BottomNavigationView
我正在尝试更新我的应用程序以使用 BottomNavigationView
。第一个选项卡包含一个 HostFragment
和一个加载微调器,该微调器执行网络请求以确定哪个片段(HomeFragment
或 LockedFragment
应显示在该选项卡中。
MainActivity
处理 BottomNavigationView
:
的初始设置
class MainActivity : AppCompatActivity() {
private lateinit var navController: NavController
private lateinit var appBarConfiguration: AppBarConfiguration
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val navHostFragment = supportFragmentManager.findFragmentById(
R.id.nav_host_container
) as NavHostFragment
navController = navHostFragment.navController
val bottomNavigationView = findViewById<BottomNavigationView>(R.id.bottom_nav)
bottomNavigationView.setupWithNavController(navController)
appBarConfiguration = AppBarConfiguration(
setOf(R.id.mainFragment)
)
setupActionBarWithNavController(navController, appBarConfiguration)
}
我的主导航图如下所示:
<?xml version="1.0" encoding="utf-8"?>
<navigation
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/nav_graph"
app:startDestination="@+id/home">
<include app:graph="@navigation/home"/>
<include app:graph="@navigation/list"/>
<include app:graph="@navigation/form"/>
</navigation>
主图如下所示:
<?xml version="1.0" encoding="utf-8"?>
<navigation
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/home"
app:startDestination="@+id/hostFragment">
<fragment
android:id="@+id/hostFragment"
android:name="com.example.android.bottomnav.homescreen.HostFragment"
android:label="Host">
<action
android:id="@+id/action_hostFragment_to_homeFragment"
app:destination="@id/homeFragment" />
<action
android:id="@+id/action_hostFragment_to_lockedFragment"
app:destination="@id/lockedFragment" />
</fragment>
<fragment
android:id="@+id/homeFragment"
android:name="com.example.android.bottomnav.homescreen.HomeFragment"
android:label="Home" />
<fragment
android:id="@+id/lockedFragment"
android:name="com.example.android.bottomnav.homescreen.LockedFragment"
android:label="Locked"/>
</navigation>
HostFragment
显示正常并加载数据:
class HostFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_host, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
determineFragmentToShow()
}
private fun determineFragmentToShow() {
lifecycleScope.launchWhenStarted {
// mock network call to determine tab
delay(1500)
// show HomeFragment for the sake of the example, but note that
// this would be dependent on the network call's result above
findNavController().navigate(R.id.action_hostFragment_to_homeFragment)
}
}
}
成功导航到 HomeFragment
。
现在的问题是,每当我从 HomeFragment
按下后退按钮时,它都会返回 HostFragment
而不是关闭应用程序。You can see the behavior in this video here.
我尝试在 home.xml
中设置 popUpTo
和 popUpInclusive
标签,如下所示:
<fragment
android:id="@+id/hostFragment"
android:name="com.example.android.bottomnav.homescreen.HostFragment"
android:label="Host">
<action
android:id="@+id/action_hostFragment_to_homeFragment"
app:destination="@id/homeFragment"
app:popUpTo="@id/home"
app:popUpToInclusive="true"/>
<action
android:id="@+id/action_hostFragment_to_lockedFragment"
app:destination="@id/lockedFragment"
app:popUpTo="@id/home"
app:popUpToInclusive="true"/>
</fragment>
当从 HomeFragment
返回时,应用程序会关闭,但现在每次我切换到新选项卡时,它都会创建一个新的片段实例并将其添加到后台堆栈。然后按下后退按钮将向后遍历它们。 You can see that behavior in this video here.
那么如何更新嵌套导航图的起始目的地呢?
我正在使用最新的 2.4.0-alpha10
导航组件,这样我就可以获得对多个后台堆栈的本机支持。非常感谢任何帮助!
我能够利用答案 here 获得适合我的解决方案。
在 HostFragment
中的 determineFragmentToShow()
内部,我只是将 findNavController().navigate(R.id.action_hostFragment_to_homeFragment)
替换为
val navController = findNavController()
val graph = navController.graph
val walletGraph = graph.findNode(R.id.home) as NavGraph
walletGraph.setStartDestination(R.id.homeFragment)
navController.navigate(R.id.action_hostFragment_to_homeFragment)
我仍然需要在此处包含 popUpTo
和 popUpInclusive
标签
<fragment
android:id="@+id/hostFragment"
android:name="com.example.android.bottomnav.homescreen.HostFragment"
android:label="Host">
<action
android:id="@+id/action_hostFragment_to_homeFragment"
app:destination="@id/homeFragment"
app:popUpTo="@id/home"
app:popUpToInclusive="true"/>
<action
android:id="@+id/action_hostFragment_to_lockedFragment"
app:destination="@id/lockedFragment"
app:popUpTo="@id/home"
app:popUpToInclusive="true"/>
</fragment>
但这让我得到了我想要的背部行为!
我正在尝试更新我的应用程序以使用 BottomNavigationView
。第一个选项卡包含一个 HostFragment
和一个加载微调器,该微调器执行网络请求以确定哪个片段(HomeFragment
或 LockedFragment
应显示在该选项卡中。
MainActivity
处理 BottomNavigationView
:
class MainActivity : AppCompatActivity() {
private lateinit var navController: NavController
private lateinit var appBarConfiguration: AppBarConfiguration
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val navHostFragment = supportFragmentManager.findFragmentById(
R.id.nav_host_container
) as NavHostFragment
navController = navHostFragment.navController
val bottomNavigationView = findViewById<BottomNavigationView>(R.id.bottom_nav)
bottomNavigationView.setupWithNavController(navController)
appBarConfiguration = AppBarConfiguration(
setOf(R.id.mainFragment)
)
setupActionBarWithNavController(navController, appBarConfiguration)
}
我的主导航图如下所示:
<?xml version="1.0" encoding="utf-8"?>
<navigation
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/nav_graph"
app:startDestination="@+id/home">
<include app:graph="@navigation/home"/>
<include app:graph="@navigation/list"/>
<include app:graph="@navigation/form"/>
</navigation>
主图如下所示:
<?xml version="1.0" encoding="utf-8"?>
<navigation
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/home"
app:startDestination="@+id/hostFragment">
<fragment
android:id="@+id/hostFragment"
android:name="com.example.android.bottomnav.homescreen.HostFragment"
android:label="Host">
<action
android:id="@+id/action_hostFragment_to_homeFragment"
app:destination="@id/homeFragment" />
<action
android:id="@+id/action_hostFragment_to_lockedFragment"
app:destination="@id/lockedFragment" />
</fragment>
<fragment
android:id="@+id/homeFragment"
android:name="com.example.android.bottomnav.homescreen.HomeFragment"
android:label="Home" />
<fragment
android:id="@+id/lockedFragment"
android:name="com.example.android.bottomnav.homescreen.LockedFragment"
android:label="Locked"/>
</navigation>
HostFragment
显示正常并加载数据:
class HostFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_host, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
determineFragmentToShow()
}
private fun determineFragmentToShow() {
lifecycleScope.launchWhenStarted {
// mock network call to determine tab
delay(1500)
// show HomeFragment for the sake of the example, but note that
// this would be dependent on the network call's result above
findNavController().navigate(R.id.action_hostFragment_to_homeFragment)
}
}
}
成功导航到 HomeFragment
。
现在的问题是,每当我从 HomeFragment
按下后退按钮时,它都会返回 HostFragment
而不是关闭应用程序。You can see the behavior in this video here.
我尝试在 home.xml
中设置 popUpTo
和 popUpInclusive
标签,如下所示:
<fragment
android:id="@+id/hostFragment"
android:name="com.example.android.bottomnav.homescreen.HostFragment"
android:label="Host">
<action
android:id="@+id/action_hostFragment_to_homeFragment"
app:destination="@id/homeFragment"
app:popUpTo="@id/home"
app:popUpToInclusive="true"/>
<action
android:id="@+id/action_hostFragment_to_lockedFragment"
app:destination="@id/lockedFragment"
app:popUpTo="@id/home"
app:popUpToInclusive="true"/>
</fragment>
当从 HomeFragment
返回时,应用程序会关闭,但现在每次我切换到新选项卡时,它都会创建一个新的片段实例并将其添加到后台堆栈。然后按下后退按钮将向后遍历它们。 You can see that behavior in this video here.
那么如何更新嵌套导航图的起始目的地呢?
我正在使用最新的 2.4.0-alpha10
导航组件,这样我就可以获得对多个后台堆栈的本机支持。非常感谢任何帮助!
我能够利用答案 here 获得适合我的解决方案。
在 HostFragment
中的 determineFragmentToShow()
内部,我只是将 findNavController().navigate(R.id.action_hostFragment_to_homeFragment)
替换为
val navController = findNavController()
val graph = navController.graph
val walletGraph = graph.findNode(R.id.home) as NavGraph
walletGraph.setStartDestination(R.id.homeFragment)
navController.navigate(R.id.action_hostFragment_to_homeFragment)
我仍然需要在此处包含 popUpTo
和 popUpInclusive
标签
<fragment
android:id="@+id/hostFragment"
android:name="com.example.android.bottomnav.homescreen.HostFragment"
android:label="Host">
<action
android:id="@+id/action_hostFragment_to_homeFragment"
app:destination="@id/homeFragment"
app:popUpTo="@id/home"
app:popUpToInclusive="true"/>
<action
android:id="@+id/action_hostFragment_to_lockedFragment"
app:destination="@id/lockedFragment"
app:popUpTo="@id/home"
app:popUpToInclusive="true"/>
</fragment>
但这让我得到了我想要的背部行为!