An Android app with only one screen can be kind of dull. Here we learn how to switch between screens with Android Navigation. We take on clicklisteners on a recyclerview, passing arguments and the famous back stack.

A great way to start your journey into Android Navigation is to read the getting started guide here.

We will pick up the example we worked on in a previous post on Android Room and add some navigation.

The Details Screen

First off we want to click on an action in the list on the home screen and go to a separate details screen. On the constraint layout of the list item we set a click listener and add it as a data variable.

android:onClick="@{() -> clickListener.onClick(action)}"

In the ActionAdapter we define the click listener and bind it to the data variable in the bind method.

class ActionListener(val clickListener: (code: UUID) -> Unit) {
    fun onClick(action: Action) = clickListener(action.code)
}

In the fragment we create the adapter and we give the click listener to the constructor.

val adapter = ActionAdapter(ActionListener { code ->
    homeViewModel.onActionClicked(code)
})

In the ViewModel we define the action of the click in the onActionClicked method.

private val _navigateToDetails = MutableLiveData<String>()
val navigateToDetails: LiveData<String>
    get() = _navigateToDetails

fun onActionClicked(code: UUID) {
    _navigateToDetails.value = code.toString()
}

The MutableLiveData is encapsulated by the LiveData so only the ViewModel can manipulate the content. The click sets the code of the clicked action on the stream. In the fragment the real navigation takes place by subscribing to the stream.

 homeViewModel.navigateToDetails.observe(this, Observer { code ->
     code?.let {
          this.findNavController().navigate(         HomeFragmentDirections.actionHomeFragmentToDetailFragment(code))
          homeViewModel.onNavigated()
     }
})

Note that the target of the navigation is generated based on an android resource file navigation.xml. The NavController knows what to do with this target and needs a context (this) like a fragment to work.

Navigation.xml

After the details screen we want to select that we have actually done an action and get a confirmation screen. I can imagine if you have trouble following. The android team has developed a design tab for the navigation file to help us with this.

Screenshot 2019 10 25 at 15.28.12 - ANDROID NAVIGATION

The only thing we need to do is provide the fragments. (We will not go into detail of how to create the detail- and doneFragment.) We can just drag the arrows between the fragments and the actions, like actionHomeFragmentToDetailFragment, will be generated.

The details fragment has to fetch the selected action from the database so navigating to the details fragment needs the action’s code. We can specify this as an argument of the fragment in the navigation file. In the text view this looks like so:

<fragment
    android:id="@+id/detailFragment"   android:name="nl.sybrenbolandit.gardenplanner.fragment.detail.DetailFragment"
    android:label="fragment_detail"
    tools:layout="@layout/fragment_detail" >
    <action
        android:id="@+id/action_detailFragment_to_doneFragment"
        app:destination="@id/doneFragment" />
    <argument
        android:name="code"
        app:argType="string" />
</fragment>

In the details fragment we have to get a hold of these arguments. We use android safeargs plugin to retrieve these arguments in a typesafe way.

val arguments = DetailFragmentArgs.fromBundle(arguments!!)
detailViewModel.fetchAction(UUID.fromString(arguments.code))

The DetailFragmentArgs will also be generated based on the navigation file and arguments.code is now safe to use as type String.

The Back Stack

Did you notice that when running the app the back button automatically worked? The android team has done a great job to make this behaviour consistent across different apps.

Only after completing an action we don’t want to go back to the details of that action but to the home screen. Android keeps track of a stack of all the screens you have visited, called the back stack. The detail screen was the last one to visit so that is where we will go. This can be overridden by popping things from the stack up to a specific screen.

Screenshot 2019 10 25 at 16.10.35 - ANDROID NAVIGATION

Here we see the design tab of the navigation file. On the right we specify the pop behaviour of the selected action. In stead of the details screen we pop everything up to the home fragment. This will give us the best user experience.

Hopefully you can now create your own customer journey by navigation them through your app with Android Navigation. Happy navigating!