Navigation is one of the core concepts to master if you are working on any Android app having a complex navigation system. Properly handled navigation also helps to reduce any security flaw in your app, like authenticating the user before navigating to any sensitive content of the app or preventing any sensitive information to be shared with other apps on the device.
There is a constant improvement to the navigation system used in Android since the past one year. And this has introduced a lot of new concepts.
In this article, I will cover some of the important concepts of Android Navigation that come with the Android Jetpack’s Navigation component.
What is the Jetpack Navigation component?
The Android Jetpack Navigation component is a suite of libraries, tooling,and guidance that provides a robust navigation framework for in-app navigation.
The Navigation component also provides some other benefits like:
- Handing fragment transactions
- Handling Up and Back actions correctly by default
- Implementing deep linking
- Navigation UI patterns, like navigation drawer, bottom navigation, etc.
- Support for Safe Args
ViewModel
support- Passing data using Android Bundle
- Listening to navigation changes
- Animating navigation
- Testing navigation
The Navigation component works both with Activities and Fragments. In the sample app, we will be mostly working with Fragments as they also provide good integration with Android’s underlying lifecycle.
When you navigate to different Activities, the application maintains a stack known as Back Stack. It helps to handle the up and back button behavior inside the app. The Fragments also maintain a back stack, but in this case, the entire Fragment Back Stack is contained within the Activity.
The Navigation component adheres to an established set of Android Navigation principles. Let’s take a look at them.
Principles of Android Navigation
To give users a consistent and intuitive user experience across a wide variety of Android apps, there are some core principles followed by navigation. Navigation component is designed to implement these principles by default.
- There’s always a starting place: Every Android app should have a fixed start destination. This is the screen user sees every time when they open the app. And while they navigate back from other screens within the app using the Up button, this the last screen they see.
- A back stack is always maintained: When a user navigates to different Activities or Fragments inside the app, there is a back stack that is always maintained. It helps in navigation the user back to the correct destination from where they came, as they go Up or Back. It follows a Last In First Out (LIFO) structure.
— Start Destination is present lower in the stack
— Current Destination is present at the top of the stack
— New Destinations are pushed to the top of the stack
— While going back the current destination is popped off the stack - Up versus Back: Both Up and Back buttons act in a similar way. Except the Up button is only used for navigating inside an app, it will never navigate you out of the app. So, the Up button should never be shown at the first screen of the app. Whereas, the Back button can take you outside of the app to the screen that is present down the navigation hierarchy.
- Deep linking simulates manual navigation: Whether you use deep linking or manually navigate to a certain screen inside an app, the back stack is populated with the same screens. So, if you have navigated to a certain page using deep linking, while you go back, the same back stack will be used as you will get if navigating to that screen manually.
Key parts of the Navigation component
The Navigation component consists of three main parts:
- Navigation graph: It manages your app’s navigation. It is a resource file that consists of the destinations along with the actions, which are used for navigating to another destination from the current one.
NavHost
: An empty container that displays destinations from your navigation graph.NavController
: It helps in managing app navigation within aNavHost
. It orchestrates the swapping of destination content using theNavHost
as users move throughout your app.
The Navigation Editor helps in visualizing and editing the whole navigation system used in your app, consisting of navigation graphs, arguments, transition animations & deep links.
Our goal
We will be building an app called Quotes Trivia, in which the user has to guess the correct person who had said the displayed memorable quote.
As the main focus of this article is Navigation, we will be mostly covering concepts related to that. But if you want to take a closer look at the UI and logic of the app, you may head over to the GitHub repo of the sample app, present at the end of this article.
Set up the Navigation component
We will be using the Android KTX version of the dependencies as we are using Kotlin language in our project. But if you are using Java, non-ktx version of the same dependencies are also available.
For using the Navigation component, add the following dependencies to your build.gradle (app)
file:
Add the Navigation graph
Create a new xml
file by right-clicking on the res folder and selecting New> Android Resource File. Select the Resource type as Navigation and use the file name navigation
.
Link navigation resource file
You have to link the navigation.xml
file in your activity_main.xml
file by adding a NavHostFragment
to use it for navigating across different Fragments of your app.
Add a fragment to the graph
Go to the Navigation Editor of the navigation.xml
file. Click on the New Destination button and select the screen that you want to add to the Navigation graph.
Navigate to another destination
For navigation from the current destination to any other, first of all create an action in the navigation graph.
You have to write the Kotlin code explicitly for triggering the action that you have defined in the Navigation graph.
Conditional Navigation
We will use conditional navigation for deciding whether to navigate the user to WonFragment
or LostFragment
. For our trivia game, the user who manages to answer around 80% of the questions correctly will be considered as the winner.
Set up the actions from the TriviaFragment
to the two Fragments, to which navigation is possible.
Triggering the actions from the Kotlin code:
Manipulate the back stack
If you try to go back from the WonFragment
or LostFragment
, the app will take you to the TriviaFragment
. But, this shouldn't be the default action as the user might want to go back directly to the home screen. Also, there are NEXT MATCH and PLAY AGAIN buttons, if someone wants to play the game again.
So, for taking the user directly from the WonFragment
or LostFragment
to the WelcomeFragment
, we have to manipulate the Back Stack. This can be done easily by setting the Pop Behavior
of any action from the Navigation Editor.
We will set the pop behavior of the action_triviaFragment_to_wonFragment
& action_triviaFragment_to_lostFragment
to popUpTo TriviaFragment
(inclusive).
Using Safe Args
Safe Args is a Gradle plugin that generates simple object and builder classes for type-safe navigation and also simplifies argument passing.
Add the following classpath
to your project's top-level build.gradle
file:
Apply the plugin in your app-level build.gradle
file:
This generates Kotlin code suitable for Kotlin-only modules. If you are using Java language or mixed Java and Kotlin modules, then use the following:
Do a clean build of the project.
Now, you can replace the id(s) used for specifying navigation actions with the generated NavDirections
classes, like this:
Pass data between fragments
You can add the arguments that you want to pass directly from the Navigation Editor
by selecting a Fragment.
Do a clean build.
For passing the arguments from a Fragment, you have to modify the Kotlin code as follows:
Android Bundle is used for retrieving the arguments in the navigated destination:
Add support for the Up button
The NavigationUI
can handle the Up button behavior by itself so that you don't have to manage it explicitly. It also automatically hides the Up button when we are at the home screen of the app.
Inside the MainActivity, link the NavController
to the ActionBar
:
Then, override the onSupportNavigateUp
method from the activity:
This will take care of all the navigation between different Fragments of this Activity.
Add an overflow menu
Let’s add an overflow menu that will navigate the user to the AboutFragment
. It would only be shown in the WelcomeFragment
of our app.
Add the AboutFragment
to the Navigation graph, but do not create any action for it.
Create a new menu resource, called overflow_menu
by right-clicking on resand selecting New > Android Resource File.
Declare an item
with the same id
as of the Fragment you want it to navigate to.
To show the menu only in the WelcomeFragment
, add the following to the Fragment:
Override the onCreateOptionsMenu
and inflate the menu resource:
Override the onOptionsItemSelected
to connect it to our NavigationUI
:
Add Navigation Drawer
Navigation Drawer component is a part of the Android Material Design Library. It is a UI panel that can be opened by swiping from the left edge of the screen, or by clicking on the menu icon present in the ActionBar
. It is typically present in apps with five or more screens.
Add the Gradle dependency of Material Design to the app level build.gradle
file:
Add one more Fragment to the Navigation graph called RulesFragment
.
Create a new menu resource named navdrawer_menu
and add two item
to it.
In the activity_main.xml
wrap the LinearLayout
with the DrawerLayout
:
Add the NavigationView
at the bottom of the DrawerLayout
.
Now, go to the MainActivity:
- Add two variables:
private lateinit var drawerLayout: DrawerLayout private lateinit var appBarConfiguration: AppBarConfiguration
- Initialize the
DrawerLayout
insideonCreate
:
drawerLayout = binding.drawerLayout
- Modify to include the drawer:
NavigationUI.setupActionBarWithNavController(this, navController, drawerLayout)
- Create an
AppBarConfiguration
and hook up theNavigationUI
up to the navigation view:
appBarConfiguration = AppBarConfiguration(navController.graph, drawerLayout)NavigationUI.setupWithNavController(binding.navView, navController)
- In the
onSupportNavigateUp
method, replace the following:
return navController.navigateUp()
with this:
return NavigationUI.navigateUp(navController, drawerLayout)
This helps in replacing the Up button with the menu button when we reach to the first screen of the app.
You can add a headerLayout
property to the NavigationView
inside activity_main.xml
:
The nav_header.xml
file looks like this:
Listen to navigation changes
Though you cannot see the menu button on other pages except the first screen, you will still be able to access the Navigation Drawer by swiping from the left edge of the screen on other pages.
In order to fix this issue and prevent it from opening on any other pages, we have to listen to the navigation changes and only enable the drawer on the first screen.
In your MainActivity file inside onCreate
method, add the following:
Now, you will not the able to open the Navigation Drawer from any other pages except the first screen.
Add a share button
You will always like to share your winning score with your friends. So, let’s add a Share button using Intent to our app.
Intents can be primarily of two types:
- Explicit Intent: For launching Activities within the same app
- Implicit Intent: It helps to provide an abstract description of the action that you want to perform, which is used for launching Activities of other apps on the device.
If multiple Android apps are present on the user’s device that can handle a specific implicit intent, then a chooser pops up.
Create a new menu resource file called share_menu
.
Add a menu item to it:
We want to show the share icon only in the WonFragment
, so we will need to setup only in that Fragment.
Inside onCreateView
add:
Create a method to define the Intent:
Method for starting the Activity:
Override the onCreateOptionsMenu
method, inflate the menu resource, and show the share button only when there is an app installed on the user's device that can handle that implicit intent.
Override onOptionsItemSelected
method to handle the action when the share button is clicked.
Animate navigation
You can apply different types of animations to the Navigation.
First of all, create a new animation resource file by right-clicking on the resfolder and selecting New > Android Resource File.
Let’s define a fading animation:
A sliding animation can be defined as follows:
You can use the Navigation Editor for applying the animations directly.
After applying all animations, the app looks like this:
Conclusion
Android Navigation Component makes the whole navigation system of the app easily manageable. The Navigation Editor, along with the navigation graph gives a good overview of the destinations, actions, arguments, and animations used in the app. Though we have covered most of the core features in this article, the Navigation component has a lot more awesome features to explore.
Originally published on Codemagic Blog.
GitHub repo of the sample app is available in the following link:
sbis04/quotes_trivia |
![]() |
Learn More