Reputation: 300
I have a Single Activity
project with Navigation Drawer
. And I realized the navigation possibility by Navigation Components
. I created a nav_graph.xml
that can route and open each Fragment
from the Navigation Drawer
. And it is enough for one level routing. But my project has two and sometimes three-level routing. So I created a nested navigation graph for that 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>
and the nested graph is:
<?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>
If I choose Settings
from Navigation Drawer
the app opens it. And then I click on ads
/ app
/ home
button and the opens the next Fragment
. But If I click back
button or arrow in the app toolbar - nothing is happening.
How to solve that issue? How to navigate back in nested graph from the third level to the second level?
upd 01 // added function that sets up the NavController and AppBarConfiguration
private fun initNavigation() {
mNavController = findNavController(R.id.navHostFragment)
navView.setupWithNavController(mNavController)
mAppBarConfiguration = AppBarConfiguration(mNavController.graph, drawerLayout)
setupActionBarWithNavController(mNavController, mAppBarConfiguration)
}
upd02
I have found one helpful thing/bug. The back button is working fine without any additional code. But when I click on the back button the app repeats the previous action "go from SettingsFragment to SettingsAdsFragment", for example.
I use moxy lib with default strategy - AddToEndSingleStrategy
.
Upvotes: 0
Views: 2032
Reputation: 300
I have found the solution!
I should use the correct strategy for the Moxy library. Yes, I didn't say anything about that lib in the topic because I didn't think that it can break the app flow.
Old Strategy type for interface methods
StateStrategyType(AddToEndSingleStrategy::class)
interface SettingsView : BaseMvpView {
fun showManageAdsFragment()
fun showManageAppUIFragment()
fun showManageHomeUIFragment()
}
New Strategy type for interface methods
StateStrategyType(SkipStrategy::class)
interface SettingsView : BaseMvpView {
fun showManageAdsFragment()
fun showManageAppUIFragment()
fun showManageHomeUIFragment()
}
Upvotes: 0
Reputation: 1463
From your comment, I think your onSupportNavigateUp()
is not entirely correct. I have implemented several apps with navDrawer and navigation, and the way I override onSupportNavigateUp()
is as follow:
// 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)
}
}
}
}
Then, for top level fragments, i.e. those acessible directly from the navDrawer:
class TopLevelFragment : Fragment() {
...
override fun onResume() {
super.onResume()
(activity as? HostActivity)?.setNavigation(false)
}
}
And for lower level fragments (ads/app/home):
class LowLevelFragment : Fragment() {
...
override fun onResume() {
super.onResume()
(activity as? HostActivity)?.setNavigation(true)
}
}
This should work, assuming you have your mNavController
and mAppBarConfiguration
correctly set up.
Upvotes: 1