Android Navigation Architecture Component Tutorial
Android Studio 3.2 is finally on the stable channel and that means we can try Android Jetpack without too much headache. The first thing I want to try is the Navigation Architecture Component (NAC). Version 3.2 provides a Navigation Editor which resembles Xcode’s Storyboard, so now we can communicate the application flow to non-technical team in a more intuitive way.
Install Dependencies
First thing first, we should install all the dependencies required to utilise the NAC. As of Android Studio 3.2.1, these dependencies are not included by default when we create a new project.
// app level build.gradle
apply plugin: 'com.android.application'
apply plugin: 'androidx.navigation.safeargs'
...android {
...
}dependencies {
...
implementation "android.arch.navigation:navigation-fragment-ktx:$nav_version"
implementation "android.arch.navigation:navigation-ui-ktx:$nav_version"
}// project level build.gradle
buildscript {
...
ext.nav_version = '1.0.0-alpha06'
dependencies {
...
classpath "android.arch.navigation:navigation-safe-args-gradle-plugin:$nav_version"
}
...
}
Create Navigation Resources
To create a new navigation resources, we can go to File -> New -> Android Resource File. Pick a name and choose “Navigation” in Resource Type and click “OK”. This will create a navigation
resource directory if we are yet to have it, and create a nav_graph.xml
file. Let’s open the nav_graph.xm
file and we will have a nice Navigation Editor in the design tab. We can see on the right side of the editor, there is a Destinations pane which have two sections: Host and Graph. The Graphs are the view that we are able to navigate into. Each Graph will be swapped in and out to the Host when the navigation happen.
Create Navigation Host
In this example, we will use our MainActivity as our Navigation Host. To do this we will need to insert a navigation fragment inside our activity_main.xml
and override onSupportNavigateUp
method to handle the back navigation.
// activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent"
android:layout_width="match_parent"
tools:context=".MainActivity">
<fragment
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
app:navGraph="@navigation/nav_graph"
app:defaultNavHost="true"/>
</androidx.constraintlayout.widget.ConstraintLayout>// MainActivity.kt
...
class MainActivity : AppCompatActivity() {
...
override fun onSupportNavigateUp(): Boolean = findNavController(R.id.nav_host_fragment).navigateUp()
}
Create Navigation Graph
In this example we will create two fragments and navigate between these two. Let’s open the Navigation Editor and click “New Destination”. In the dialog that appears, choose “Create blank destination” or if we already have created activity or fragment, we can choose them too. But for now, let’s create a blank.
Pick a name for the new fragment and click “Finish”. We can check the “Include fragment factory methods” and “Include interface callbacks?” if we need to. Then, our newly generated fragment will be displayed in the Navigation Editor. Let’s repeat this step to have another fragment to navigate into.
After we have the second fragment, hover on the first fragment. There will be a circle on the right side of the fragment. Click it and drag to the second fragment. Now, we have the first fragment connected to the second one. If we click the arrow between these two fragments, we can see the action attribute on the right side of the Navigation Editor.
Add Navigation Trigger
Now, the movement between these two fragments should be triggered by something, right? To try this, let’s create a single button on the first fragment. Make it whatever we want, but pay attention to the button’s id.
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
...
>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:text="Go"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>
Next, we will invoke the navigation when the button is pressed by setting an on-click listener.
// BlankFragment.kt
...
button.setOnClickListener {
it.findNavController().navigate(R.id.action_blankFragment_to_formFragment)
}
...
So, what happen here? First, to invoke the navigation, we need to use the NavController
class which we retrieve by calling findNavController.
Then, we invoke the navigate
method that receive resource id specifying the navigation action we want to run. This action id can be found by going to the Navigation Editor, clicking the arrow, and it will be available in Attributes pane. Now, if everything is good, we would have a nice transition between the first and second fragment when tapping the button.
That’s all for now. I’ll be covering how we might pass some parameters between navigation and how we tie the navigation trigger to other UI component such as bottom navigation in the next article.