Reputation: 10569
I want to use the new navigation graph and the BottomNavigationView
. I got the following dependencies:
// Navigation
implementation "androidx.navigation:navigation-fragment-ktx:$navVersion"
implementation "androidx.navigation:navigation-ui-ktx:$navVersion"
implementation "androidx.fragment:fragment:1.2.2"
// Material
implementation "com.google.android.material:material:$materialVersion"
notice the implementation "androidx.fragment:fragment:1.2.2"
which should fix the error occuring with FragmentContainerView
not appearing as host in the navigation graph.
Here is my simple navigation graph:
The first strange thing you can see here is that nothing is appearing as host, even though I added the dependency which should fix it.
My main activity layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
app:defaultNavHost="true"
app:navGraph="@navigation/navigation_graph" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?colorPrimary"
app:itemIconTint="@drawable/menu_navigation"
app:itemTextColor="@drawable/menu_navigation"
app:menu="@menu/menu_navigation" />
</LinearLayout>
and my main activity kotlin file:
class MainActivity : AppCompatActivity() {
private var navController: NavController? = null
private var appBarConfiguration: AppBarConfiguration? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
navController =
(supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment).navController
appBarConfiguration = AppBarConfiguration.Builder(
setOf(
R.id.main_fragment,
R.id.recycler_fragment,
R.id.map_fragment
)
).build()
setupActionBar()
setupBottomNavigationMenu()
}
private fun setupActionBar() {
NavigationUI.setupActionBarWithNavController(
this,
navController!!,
appBarConfiguration!!
)
}
private fun setupBottomNavigationMenu() {
bottom_navigation?.let {
NavigationUI.setupWithNavController(it, navController!!)
}
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.menu_toolbar, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
val navigated = NavigationUI.onNavDestinationSelected(item, navController!!)
return navigated || super.onOptionsItemSelected(item)
}
}
Here we also have my menu and my toolbar:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<item
android:id="@+id/destination_home"
android:icon="@drawable/ic_home"
android:title="@string/home"
tools:layout="@layout/fragment_main" />
<item
android:id="@+id/destination_recycler"
android:icon="@drawable/ic_list"
android:title="@string/recycler"
tools:layout="@layout/fragment_recycler" />
<item
android:id="@+id/destination_map"
android:icon="@drawable/ic_map"
android:title="@string/map"
tools:layout="@layout/fragment_map" />
</menu>
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/destination_settings"
android:icon="@drawable/ic_settings"
android:title="@string/settings"
app:showAsAction="ifRoom" />
</menu>
When I now start the app I would expect the following behavior:
What actually happens is:
So something is really messed up here with the navigation and I have no idea how to fix it.
Upvotes: 1
Views: 629
Reputation: 199805
Firstly, you are passing R.id.main_fragment, R.id.recycler_fragment, R.id.main_fragment
to your AppBarConfiguration
- besides including main_fragment
twice, those names don't match up with the destination_home
, destination_recycler
, and destination_map
in your menu XML. Since your clicking in your bottom nav bar works, those appear to be the correct destination IDs and you should change your AppBarConfiguration
to use the same IDs:
appBarConfiguration = AppBarConfiguration.Builder(
setOf(
R.id.destination_home,
R.id.destination_recycler,
R.id.destination_map
)
).build()
Or, if you're using the navigation-ui-ktx
artifact, you'd use the top level AppBarConfiguration
creator:
appBarConfiguration = AppBarConfiguration(setOf(
R.id.destination_home,
R.id.destination_recycler,
R.id.destination_map))
As per the onNavDestinationSelected()
Javadoc:
By default, the back stack will be popped back to the navigation graph's start destination. Menu items that have
android:menuCategory="secondary"
will not pop the back stack.
Therefore it is expected that leaving out that in your menu XML for the Settings screen would cause you to go back to the start destination of your graph when you hit the back button. You'd want to change your menu XML to include that flag:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/destination_settings"
android:icon="@drawable/ic_settings"
android:title="@string/settings"
app:showAsAction="ifRoom"
android:menuCategory="secondary" />
</menu>
Upvotes: 1