At Google I/O 2018, Android introduced a bunch of new components to the Android Jetpack libraries. One such library is Navigation component, designed to reduce the effort in building apps with consistent navigation flow and to reduce errors and making it easier to work fragments. Recently the Navigation Component moved from beta to stable.
With the navigation component, it's very easy to build consistent navigation in your apps. Not only this with the navigation component you can do a lot more:
- Fragment transaction can be done with just a single method call.
- Handling Up and Back actions correctly by default.
- Safely pass data between destination with SafeArgs.
- Native support for deep-linking.
- Building navigation drawers & bottom navigation bars with minimal code.
So now let's learn how we can use this component in our apps.
1. Add the dependencies
In your app-level build.gradle
file include the following dependencies
implementation "androidx.navigation:navigation-fragment:2.1.0"
implementation "androidx.navigation:navigation-ui:2.1.0"
If you are using kotlin append -ktx
to the above libraries
implementation "androidx.navigation:navigation-fragment-ktx:2.1.0"
implementation "androidx.navigation:navigation-ui-ktx:2.1.0"
To add support for SafeArgs, add a classpath in your project-level ```build.gradle``` file.
buildscript {
repositories {
google()
}
dependencies {
//.....
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.1.0"
}
}
Now add the following line to your app-level ```build.gradle``` file.
apply plugin: "androidx.navigation.safeargs"
2. Add Activity
Create a BaseActivity
to contain the fragments. This activity will contain the Host fragment.
Java:
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_base);
}
}
Kotlin:
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
class BaseActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_base)
}
}
Now add a layout file activity_base.xml
that contains a fragment. This fragment will be our NavHost fragment i.e, An empty container to display our destination fragments.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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"
tools:context=".ui.BaseActivity">
<fragment
android:id="@+id/base_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:defaultNavHost="true" />
</androidx.constraintlayout.widget.ConstraintLayout>
android:name
signifies that this fragment is a host for our destination and app:defaultNavHost
when set to true tells that this is the default host for all the destination in our app.
3. Add the Navigation Graph
Navigation graph is an XML resource file that contains all the navigation-related information in a single file. It contains all the information about destinations and paths. It can be visually edited from Android Studio 3.3 onwards.
To add the navigation graph: Right-click on the resource(res) folder in the Project menu> select New > select Android Resource File.
Now add this graph file to the NavHost fragment we just created above as app:navGraph="@navigation/nav_graph"
<fragment
android:id="@+id/base_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/nav_graph"
/>
4. Create Destinations
On the navigation graph editor find the add destination button and then click on 'Create new Destination'.
Now a fragment creation window opens up. Let's name our fragment HomeFragment.
Set the HomeFragment as our start destination by using the home icon in the toolbar.
Now let's add another destination and name it DestFragment. Now our navigation graph looks like below.
Click on the homeFragment destination and drag a path from homeFragment to destFragment destination.
Let's add a button to our HomeFragment. When clicking the button the DestFragment should open.
Go to fragment_home.xml
& Add a button
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
tools:context=".HomeFragment">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Open DEST"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Now in HomeFragment.kt
or HomeFragment.java
file override the onViewCreated
method and set a listener for the button we just added. Then use the navigate method of NavController object to switch to destFragment destination.
Java
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
public class HomeFragment extends Fragment {
public HomeFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_home, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
final NavController navController =
Navigation.findNavController(requireActivity(), R.id.base_fragment);
Button button = getActivity().findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
navController.navigate(R.id.destFragment);
}
});
}
}
Kotlin
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.navigation.fragment.findNavController
import kotlinx.android.synthetic.main.fragment_home.*
class HomeFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_home, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
button.setOnClickListener {
findNavController().navigate(R.id.destFragment)
}
}
}
This is it. See how easy it is to switch fragments. I'll write about using navigation graph with BottomNavigationBar in my next post in the series.
You can find the sample code used in this article here.
Originally published at A coder’s words.
Top comments (0)