我有一个带有Navigation Drawer
的Single Activity
项目。并通过Navigation Components
实现了导航的可能性。我创建了一个nav_graph.xml
,它可以从Navigation Drawer
路由并打开每个Fragment
。这对于一级路由来说已经足够了。但我的项目有两个,有时还有三个路由。因此,我为nav_nested_settings
创建了一个嵌套导航图。
<?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/nav_fragment_home">
<fragment
android:id="@+id/nav_fragment_home"
android:name="com.app.ui.fragment.home.HomeFragment"
android:label="@string/nav_home"
tools:layout="@layout/fragment_home">
// other actions ...
<action
android:id="@+id/action_nav_fragment_home_to_nav_fragment_fragment"
app:destination="@id/nav_nested_settings" />
</fragment>
// ... other fragments
<fragment
android:id="@+id/nav_fragment_search"
android:name="com.app.ui.fragment.search.SearchFragment"
android:label="@string/nav_search"
tools:layout="@layout/fragment_search" />
<include app:graph="@navigation/nav_settings" />
</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"
xmlns:tool="http://schemas.android.com/tools"
android:id="@+id/nav_nested_settings"
android:label="@string/nav_settings"
app:startDestination="@id/nav_fragment_settings">
<fragment
android:id="@+id/nav_fragment_settings"
android:name="com.app.ui.fragment.settings.main.SettingsFragment"
android:label="@string/nav_settings"
tool:layout="@layout/fragment_settings">
<action
android:id="@+id/action_nav_fragment_settings_to_nav_fragment_settings_ads"
app:destination="@id/nav_fragment_settings_ads" />
<action
android:id="@+id/action_nav_fragment_settings_to_nav_fragment_settings_app"
app:destination="@id/nav_fragment_settings_app" />
<action
android:id="@+id/action_nav_fragment_settings_to_nav_fragment_settings_home"
app:destination="@id/nav_fragment_settings_home" />
</fragment>
<fragment
android:id="@+id/nav_fragment_settings_ads"
android:name="com.app.ui.fragment.settings.ads.SettingsAdsFragment"
android:label="@string/nav_settings_ads"
tool:layout="@layout/fragment_settings_ads" />
<fragment
android:id="@+id/nav_fragment_settings_app"
android:name="com.app.ui.fragment.settings.app.SettingsAppFragment"
android:label="@string/nav_settings_app"
tool:layout="@layout/fragment_settings_app" />
<fragment
android:id="@+id/nav_fragment_settings_home"
android:name="com.app.ui.fragment.settings.home.SettingsHomeFragment"
android:label="@string/nav_settings_home"
tool:layout="@layout/fragment_settings_home">
</fragment>
</navigation>
如果我从Navigation Drawer
中选择Settings
,应用程序会打开它。然后我单击ads
/app
/home
按钮,打开下一个Fragment
。但如果我单击应用程序工具栏中的back
按钮或箭头,则不会发生任何事情。
如何解决这个问题?如何在嵌套图中从第三级导航回第二级?
upd 01//添加了设置NavController和AppBarConfiguration 的功能
private fun initNavigation() {
mNavController = findNavController(R.id.navHostFragment)
navView.setupWithNavController(mNavController)
mAppBarConfiguration = AppBarConfiguration(mNavController.graph, drawerLayout)
setupActionBarWithNavController(mNavController, mAppBarConfiguration)
}
upd02我发现了一个有用的东西/错误。后退按钮工作正常,没有任何附加代码。但当我点击后退按钮时,应用程序会重复上一个动作";从设置碎片到设置碎片";,例如我使用默认策略为AddToEndSingleStrategy
的moxy-lib。
根据您的评论,我认为您的onSupportNavigateUp()
并不完全正确。我已经用navDrawer和导航实现了几个应用程序,我覆盖onSupportNavigateUp()
的方式如下:
// the activity hosting your navigation
class HostActivity : AppCompatActivity {
// flag if for the currently shown fragment, navigating up is enabled
// should be false for top level fragments, i.e. those accessible from navDrawer
// should be set to true for lower level fragments
private var canNavigateUp: Boolean = false
...
override fun onSupportNavigateUp(): Boolean {
return if (canNavigateUp) {
mNavController.navigateUp()
} else {
NavigationUI.navigateUp(mNavController, mAppBarConfiguration)
}
}
fun setNavigation(navigateUpEnabled: Boolean) {
supportActionBar?.let { actionBar ->
canNavigateUp = navigateUpEnabled
if (navigateUpEnabled) {
// set up icon
actionBar.setHomeAsUpIndicator(null)
lockUnlockDrawer(lock = true)
} else {
// set drawer icon
actionBar.setDisplayShowHomeEnabled(true)
lockUnlockDrawer(lock = false)
}
}
}
}
然后,对于顶级碎片,即那些可以直接从navDrawer访问的碎片:
class TopLevelFragment : Fragment() {
...
override fun onResume() {
super.onResume()
(activity as? HostActivity)?.setNavigation(false)
}
}
对于较低级别的片段(广告/应用程序/主页(:
class LowLevelFragment : Fragment() {
...
override fun onResume() {
super.onResume()
(activity as? HostActivity)?.setNavigation(true)
}
}
假设您正确设置了mNavController
和mAppBarConfiguration
,这应该会起作用。
我找到了解决方案!
我应该对Moxy库使用正确的策略。是的,我在主题中没有提到这个lib,因为我不认为它会破坏应用程序流。
接口方法的旧策略类型
StateStrategyType(AddToEndSingleStrategy::class)
interface SettingsView : BaseMvpView {
fun showManageAdsFragment()
fun showManageAppUIFragment()
fun showManageHomeUIFragment()
}
接口方法的新策略类型
StateStrategyType(SkipStrategy::class)
interface SettingsView : BaseMvpView {
fun showManageAdsFragment()
fun showManageAppUIFragment()
fun showManageHomeUIFragment()
}