使用导航组件时如何保留特定屏幕?
How to keep a specific screen when using Navigatioin Component?
我有一个 BottomNavigationView
,我正在使用 NavController
切换 menus
并移动 screen
。
我想知道如何在自由移动菜单时保持特定屏幕。
让我再详细解释一下。
有底部菜单A, B, C
。每个都有一个 Fragment
屏幕。
所有菜单和屏幕转换都使用 NavHost
、NavController
和 nav_graph
。
在菜单 C
中,通过 C
屏幕上的 button
显示 dialog
。
该对话框还链接到 nav_graph
。
在对话框中选择一个选项后,它会移动到屏幕 D
。
D
屏幕是你写东西的页面。
从现在开始这很重要。
当前菜单是 C
,屏幕 D
已打开,正在写入内容。
但是,如果您在写入时转到 another menu
,然后 return 到 C
,第一个菜单 C
的屏幕 C
会出现,而不是你正在写的屏幕。
在这里,我希望即使我从另一个菜单 return 时,我正在编写的屏幕也能继续显示。
有什么好的方法吗?
作为参考,由于我使用的是mvvm
模式和viewmodel
,所以我正在写入的屏幕数据似乎保持不变。
谢谢。
nav_graph
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/nav_graph"
app:startDestination="@id/calendar">
<!-- menu C screen -->
<fragment
android:id="@+id/write_home"
android:name="com.example.writeweight.fragment.WriteRoutineHomeFragment"
android:label="fragment_write_routine_home"
tools:layout="@layout/fragment_write_routine_home" >
<action
android:id="@+id/action_write_home_to_bodyPartDialog"
app:destination="@id/bodyPartDialog" />
</fragment>
<!-- dialog -->
<dialog
android:id="@+id/bodyPartDialog"
android:name="com.example.writeweight.fragment.BodyPartDialogFragment"
android:label="BodyPartDialogFragment"
tools:layout="@layout/fragment_body_part_dialog">
<action
android:id="@+id/action_bodyPartDialog_to_write"
app:destination="@id/write"/>
</dialog>
<!-- screen D (write page) -->
<fragment
android:id="@+id/write"
android:name="com.example.writeweight.fragment.WriteRoutineFragment"
android:label="WritingRoutineFragment"
tools:layout="@layout/fragment_writing_routine">
<action
android:id="@+id/action_write_to_workoutListTabFragment"
app:destination="@id/workoutListTabFragment" />
<argument
android:name="title"
app:argType="string"
app:nullable="true"
android:defaultValue="@null"/>
<argument
android:name="workout"
app:argType="string"
app:nullable="true"
android:defaultValue="@null"/>
</fragment>
</navigation>
有两种方法可以解决此问题,要么使用 version_navigation 2.4.0-alpha01,这是最简单的方法,要么使用 NavigationExtensions
要使用 NavigationExtensions,您必须将其添加到您的项目 NavigationExtensions,然后在导航菜单中为每个选项卡创建单独的导航文件。
在主 activity 布局中,将 fragment 替换为 FragmentContainerView 并删除 NavHostFragment。
在主要活动中
class MainActivity : AppCompatActivity(), NavController.OnDestinationChangedListener {
private val viewModel by viewModels<MainViewModel>()
private var currentNavController: LiveData<NavController>? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.main)
setSupportActionBar(toolbar)
/*
appBarConfiguration = AppBarConfiguration(
// navController.graph,
setOf(
R.id.navigate_home, R.id.navigate_collection, R.id.navigate_profile
),
drawerLayout
)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
bottomNavView.setupWithNavController(navController)
// make sure appbar/toolbar is not hidden upon fragment switch
navController.addOnDestinationChangedListener { controller, destination, arguments ->
if (destination.id in bottomNavDestinationIds) {
appBarLayout.setExpanded(true, true)
}
}
*/
// Add your tab fragments
val navGraphIds = listOf(R.navigation.home, R.navigation.albumlist, R.navigation.test)
val controller = bottomNavView.setupWithNavController(
navGraphIds = navGraphIds,
fragmentManager = supportFragmentManager,
containerId = R.id.nav_host_container,
intent = intent
)
// Whenever the selected controller changes, setup the action bar.
controller.observe(this, Observer { navController ->
setupActionBarWithNavController(navController)
// optional NavigationView for Drawer implementation
// navView.setupWithNavController(navController)
addOnDestinationChangedListener(navController)
})
currentNavController = controller
}
private fun addOnDestinationChangedListener(navController: NavController) {
// ensure only one listener is active
navController.removeOnDestinationChangedListener(this)
navController.addOnDestinationChangedListener(this)
}
override fun onDestinationChanged(
controller: NavController,
destination: NavDestination,
arguments: Bundle?
) {
if (destination.id in bottomNavDestinationIds) {
appBarLayout.setExpanded(true, true)
}
}}
我有一个 BottomNavigationView
,我正在使用 NavController
切换 menus
并移动 screen
。
我想知道如何在自由移动菜单时保持特定屏幕。
让我再详细解释一下。
有底部菜单A, B, C
。每个都有一个 Fragment
屏幕。
所有菜单和屏幕转换都使用 NavHost
、NavController
和 nav_graph
。
在菜单 C
中,通过 C
屏幕上的 button
显示 dialog
。
该对话框还链接到 nav_graph
。
在对话框中选择一个选项后,它会移动到屏幕 D
。
D
屏幕是你写东西的页面。
从现在开始这很重要。
当前菜单是 C
,屏幕 D
已打开,正在写入内容。
但是,如果您在写入时转到 another menu
,然后 return 到 C
,第一个菜单 C
的屏幕 C
会出现,而不是你正在写的屏幕。
在这里,我希望即使我从另一个菜单 return 时,我正在编写的屏幕也能继续显示。
有什么好的方法吗?
作为参考,由于我使用的是mvvm
模式和viewmodel
,所以我正在写入的屏幕数据似乎保持不变。
谢谢。
nav_graph
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/nav_graph"
app:startDestination="@id/calendar">
<!-- menu C screen -->
<fragment
android:id="@+id/write_home"
android:name="com.example.writeweight.fragment.WriteRoutineHomeFragment"
android:label="fragment_write_routine_home"
tools:layout="@layout/fragment_write_routine_home" >
<action
android:id="@+id/action_write_home_to_bodyPartDialog"
app:destination="@id/bodyPartDialog" />
</fragment>
<!-- dialog -->
<dialog
android:id="@+id/bodyPartDialog"
android:name="com.example.writeweight.fragment.BodyPartDialogFragment"
android:label="BodyPartDialogFragment"
tools:layout="@layout/fragment_body_part_dialog">
<action
android:id="@+id/action_bodyPartDialog_to_write"
app:destination="@id/write"/>
</dialog>
<!-- screen D (write page) -->
<fragment
android:id="@+id/write"
android:name="com.example.writeweight.fragment.WriteRoutineFragment"
android:label="WritingRoutineFragment"
tools:layout="@layout/fragment_writing_routine">
<action
android:id="@+id/action_write_to_workoutListTabFragment"
app:destination="@id/workoutListTabFragment" />
<argument
android:name="title"
app:argType="string"
app:nullable="true"
android:defaultValue="@null"/>
<argument
android:name="workout"
app:argType="string"
app:nullable="true"
android:defaultValue="@null"/>
</fragment>
</navigation>
有两种方法可以解决此问题,要么使用 version_navigation 2.4.0-alpha01,这是最简单的方法,要么使用 NavigationExtensions 要使用 NavigationExtensions,您必须将其添加到您的项目 NavigationExtensions,然后在导航菜单中为每个选项卡创建单独的导航文件。 在主 activity 布局中,将 fragment 替换为 FragmentContainerView 并删除 NavHostFragment。
在主要活动中
class MainActivity : AppCompatActivity(), NavController.OnDestinationChangedListener {
private val viewModel by viewModels<MainViewModel>()
private var currentNavController: LiveData<NavController>? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.main)
setSupportActionBar(toolbar)
/*
appBarConfiguration = AppBarConfiguration(
// navController.graph,
setOf(
R.id.navigate_home, R.id.navigate_collection, R.id.navigate_profile
),
drawerLayout
)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
bottomNavView.setupWithNavController(navController)
// make sure appbar/toolbar is not hidden upon fragment switch
navController.addOnDestinationChangedListener { controller, destination, arguments ->
if (destination.id in bottomNavDestinationIds) {
appBarLayout.setExpanded(true, true)
}
}
*/
// Add your tab fragments
val navGraphIds = listOf(R.navigation.home, R.navigation.albumlist, R.navigation.test)
val controller = bottomNavView.setupWithNavController(
navGraphIds = navGraphIds,
fragmentManager = supportFragmentManager,
containerId = R.id.nav_host_container,
intent = intent
)
// Whenever the selected controller changes, setup the action bar.
controller.observe(this, Observer { navController ->
setupActionBarWithNavController(navController)
// optional NavigationView for Drawer implementation
// navView.setupWithNavController(navController)
addOnDestinationChangedListener(navController)
})
currentNavController = controller
}
private fun addOnDestinationChangedListener(navController: NavController) {
// ensure only one listener is active
navController.removeOnDestinationChangedListener(this)
navController.addOnDestinationChangedListener(this)
}
override fun onDestinationChanged(
controller: NavController,
destination: NavDestination,
arguments: Bundle?
) {
if (destination.id in bottomNavDestinationIds) {
appBarLayout.setExpanded(true, true)
}
}}