Navigation Component for Android Part 3: Transition and Navigation
In this tutorial, you’ll learn how to use shared element transitions, action bar and bottom navigation to make an app that shows a list of random dogs images. By Ricardo Costeira.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Navigation Component for Android Part 3: Transition and Navigation
25 mins
- Getting Started
- Fetching Dependencies
- Sharing Elements Between Screens
- Adapting the Adapter
- Adding Shared Elements to NavController
- Walking the Doggo to Another View
- Teaching the RecyclerView to Stay
- Controlling the Action Bar
- Adding a Menu Item
- Implementing Bottom Navigation
- Updating Styles and Layouts
- Wiring the NavController to Bottom Navigation
- Fixing The Action Bar Navigation Button
- The Multiple Back Stacks Problem
- Where to Go From Here?
Updating Styles and Layouts
Now you’ll use the BottomNavigationView
from Material Components. In the app, navigate to res ▸ values ▸ styles.xml. Update your themes to use Material Components.
If you don’t do this, the bottom navigation bar won’t display correctly.
Simply replace AppCompat
with MaterialComponents
i.e Theme.AppCompat.DayNight.DarkActionBar
is replaced by Theme.MaterialComponents.DayNight.DarkActionBar
. Once done your styles.xml would be like below:
<resources>
<!-- Base application Theme -->
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<!-- Splash Screen Theme -->
<style name="SplashTheme" parent="Theme.MaterialComponents.NoActionBar">
<item name="android:windowBackground">@drawable/splash_background</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
</style>
</resources>
To set the destination buttons, you’ll use a menu. Right-click on the menu package, select New ▸ Menu resource file. Name it menu_bottom_nav
. Delete everything inside and add this 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/doggoList"
android:icon="@drawable/ic_list_white_24dp"
android:title="@string/doggos"
app:showAsAction="ifRoom" />
<item
android:id="@+id/favorites"
android:icon="@drawable/ic_favorite_white_24dp"
android:title="@string/favorites"
app:showAsAction="ifRoom" />
</menu>
The first item is for the doggo list. The second item is for the favorites list, which you couldn’t access until now. As with the Action Bar menu item, the IDs of these items must match the IDs of the actual nav graphs.
Now that you have the menu, you need to add a BottomNavigationView
to the layout where the NavHostFragment
is.
First, navigate to res ▸ layout and open activity_main.xml. Add the navigation view at the end of the LinearLayout
:
<?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:id="@+id/main_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".presentation.MainActivity">
<fragment
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/app" />
<!-- Bottom Navigation Component added -->
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:menu="@menu/menu_bottom_nav" />
</LinearLayout>
You should already see it in the layout preview. Build and run the app to see the real deal!
Cute, but the buttons don’t do anything. You still need to connect the BottomNavigationView
to the Navigation Component.
Wiring the NavController to Bottom Navigation
First, open MainActivity.kt. Add this line in setupBottomNavigationBar()
:
bottom_navigation.setupWithNavController(navController)
Resolve any import errors. You’re accessing the bottom nav through bottom_navigation
, a synthetic property created by Kotlin through the ID of the BottomNavigationView
in the layout.
Build and run the app. The buttons now work correctly.
Not only do the buttons work, but since you’re already controlling the Action Bar with the Navigation Component, the name of the screen updates when you click the destinations.
They go great together! However, you probably noticed the Up button appears in the Action Bar when you click Favorites. That shouldn’t happen in top-level destinations.
Fortunately, there’s a way to fix it.
Fixing The Action Bar Navigation Button
The problem is that Navigation Component doesn’t know which destinations, other than the starting one, are top-level destinations.
The AppBarConfiguration
class provides a simple solution. While still in MainActivity.kt, change appBarConfiguration
initialization to:
private val appBarConfiguration by lazy {
AppBarConfiguration(
topLevelDestinationIds = setOf(
R.id.doggoListFragment,
R.id.favoritesFragment
)
)
}
Here, you specify exactly which destinations should be considered top-level. You must pass in the IDs of the Fragments you want to treat as top-level destinations.
Build and run. That’s it!
The Multiple Back Stacks Problem
There’s one more thing before you go. Notice the back stack of a top-level destination is destroyed when you go to the other one:
This is a known issue. Navigation Component doesn’t support multiple back stacks yet.
While efforts to support the feature are in progress, it might take a while as it involves changing code at the Fragment level.
Where to Go From Here?
Impressive! You made it to the end with no doggo bites, and, best of all, now you can use Navigation Component to leverage some pretty neat navigation patterns.
Download the completed final version of the project by clicking the Download Materials button at the top or bottom of this tutorial.
For additional examples of Navigation, as well as the navigation principles, check the official documentation.
You can also check Google’s basic and advanced navigation samples.
For bottom navigation guidelines, check the material guidelines.
I hope you enjoyed this tutorial. If you have any questions, tips or want to show off your cool mapping app, feel free to join the discussion below!