The Navigation component, one of the components of Google’s Jetpack, uses Navigation diagrams to manage your app’s Navigation. A navigation diagram is a resource file that contains all of the application’s destinations and logical connections (also known as “actions” that a user can perform to navigate from one destination to another). You can use the Navigation Editor in Android Studio to manage your application’s Navigation diagram. Here’s how to use it.

I. Use of Navigation

Note: The Navigation component requires Android Studio 3.3 or higher and relies on Java 8 language features.

1.1 Adding a Dependency

To add Navigation support to your project, add the following dependencies to your app’s build.gradle file:

def nav_version = "2.3.2"
// Kotlin
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
// Feature module Support
implementation "androidx.navigation:navigation-dynamic-features-fragment:$nav_version"
Copy the code

We need to make Navigation support Safe Args to ensure type safety. The following dependencies need to be added: In your project’s build.gradle

buildscript {
    repositories {
        google()
    }
    dependencies {
        def nav_version = "2.3.2"
        classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"}}Copy the code

Add a plugin to build. Gradle in your app

// Support Java
apply plugin: "androidx.navigation.safeargs"
Copy the code

If your project is all Kotlin code, then you can use it.

// Support kotlin
apply plugin: "androidx.navigation.safeargs.kotlin"
Copy the code

1.2 Creating a Navigation Diagram

  • Right click on the res directory and select New > Android Resource File. The New Resource File dialog box is displayed.
  • Enter a name in the File name field, for example “nav_graph”.
  • Select Navigation from the Resource Type drop – down list, and click OK.

So that you can generate a navigation directory in the res directory, and generated within a nav_graph XML file, or, we can directly in the res directory, create a new directory navigation directly, and create a new nav_graph inside. The XML file, HTML code is as follows:

<? xml version="1.0" encoding="utf-8"? > <navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/nav_graph">
</navigation>
Copy the code

This nav_graph.xml file is called a navigation diagram

1.3 Add a navigation diagram to the Activity

The Activity class: NavigationTestActivity

class NavigationTestActivity :AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?). {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_navigationtest)
    }
}
Copy the code

Activity_navigationtest.xml layout file

<? 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">

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:defaultNavHost="true"
        app:navGraph="@navigation/nav_graph" />

</androidx.constraintlayout.widget.ConstraintLayout>
Copy the code
  • The android: name = “androidx. Navigation. Fragments. NavHostFragment” through the android: name attribute to specify NavHost implementation class name. Here is the NavHostFragment
  • App: navigation/nav_graph =”@navigation/nav_graph
  • App :defaultNavHost=”true” Set app:defaultNavHost to ensure that NavHostFragment intercepts the system return button. Note that there can only be one default NavHost

1.4 Adding Navigation The start destination of the Navigation view

We added two fragments to the nav_graph. XML file, one FragmentOne and one FragmentTwo, and specified FragmentOne as the startDestination, which is the first page to display. The code is as follows:

<? xml version="1.0" encoding="utf-8"? > <navigation 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/nav_graph"
    app:startDestination="@+id/fragmentOne">

    <fragment
        android:id="@+id/fragmentOne"
        android:name="com.example.jetpackdatabindingtestapp.ui.navigation.FragmentOne"
        android:label="fragment_one"
        tools:layout="@layout/fragment_one">
    </fragment>
    
    <fragment
        android:id="@+id/fragmentTwo"
        android:name="com.example.jetpackdatabindingtestapp.ui.navigation.FragmentTwo"
        android:label="fragment_two"
        tools:layout="@layout/fragment_two">
    </fragment>

</navigation>
Copy the code
  • App :startDestination means, specify the starting page. The first page the user sees when they open the app.
  • The android: id specified id
  • Android :name specifies the specific path to the page, such as the full path to FragmentOne
  • Tools: Layout This specifies the layout used by FragmentOne

We call each page defined in the navigation map a destination. The jump destination specified by app:startDestination is called the startDestination.

1.5 Navigation jump Action

For example, if we want to jump from FragmentOne to FragmentTwo, we’ll use action (also called action) as shown in nav_graph.xml:

<? xml version="1.0" encoding="utf-8"? > <navigation 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/nav_graph"
    app:startDestination="@+id/fragmentOne">

    <fragment
        android:id="@+id/fragmentOne"
        android:name="com.example.jetpackdatabindingtestapp.ui.navigation.FragmentOne"
        android:label="fragment_one"
        tools:layout="@layout/fragment_one">
        <action
            android:id="@+id/action_fragmentone_to_fragmenttwo"
            app:destination="@+id/fragmentTwo"/>
    </fragment>

    <fragment
        android:id="@+id/fragmentTwo"
        android:name="com.example.jetpackdatabindingtestapp.ui.navigation.FragmentTwo"
        android:label="fragment_two"
        tools:layout="@layout/fragment_two">
    </fragment>

</navigation>
Copy the code

Action defines the id of the action, app: Destination defines the destination of the jump, and we specify fragmentTwo. Action_fragmentone_to_fragmenttwo This action performs a jump from FragmentOne to FragmentTwo. Code for FragmentOne:

class FragmentOne :Fragment() {private varmRoot:View? =null

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup? , savedInstanceState:Bundle?).: View? {
        mRoot = inflater.inflate(R.layout.fragment_one,container,false)
        valtvClickEnterTwo = mRoot? .findViewById<View>(R.id.tv_click_enter_two) tvClickEnterTwo? .setOnClickListener{ Navigation.findNavController(mRoot!!) .navigate(R.id.action_fragmentone_to_fragmenttwo) }return mRoot
    }
}

// Fragment_one.xml layout code<? 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"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/tv_click_enter_two"
        android:layout_width="wrap_content"
        android:layout_height="50dp"
        android:text="First Fragment"
        android:gravity="center"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>
Copy the code

We can see FragmentOne code is very simple, there is a TextView controls, showing the first Fragment, TextView click will call Navigation. FindNavController (mRoot!!) .navigate(R.i.d.action_fragmentone_to_fragmentTwo) to perform a jump to FragmentTwo.

  • Navigation. FindNavController will get a NavController (view)
  • Navcontroller.navigate (r.i.d.xx) will get an Action for a View. Corresponds to the action in our layout file

So that completes the jump from FragmentOne to FragmentTwo. \

When we have multiple places that jump to a single page, say FragmentOne jumps to FragmentTwo, FragmentThree jumps to FragmentTwo. At this point we can define the action that jumps to FragmentTwo as a global operation. The code is as follows:

<? xml version="1.0" encoding="utf-8"? > <navigation 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/nav_graph"
    app:startDestination="@+id/fragmentOne">

    <fragment
        android:id="@+id/fragmentOne"
        android:name="com.example.jetpackdatabindingtestapp.ui.navigation.FragmentOne"
        android:label="fragment_one"
        tools:layout="@layout/fragment_one">
    </fragment>

    <fragment
        android:id="@+id/fragmentTwo"
        android:name="com.example.jetpackdatabindingtestapp.ui.navigation.FragmentTwo"
        android:label="fragment_two"
        tools:layout="@layout/fragment_two">
    </fragment>

    <action
        android:id="@+id/action_fragmentone_to_fragmenttwo"
        app:destination="@+id/fragmentTwo"/>
</navigation>

// Execute a jump in Java codetvClickEnterTwo? .setOnClickListener{ Navigation.findNavController(mRoot!!) .navigate(R.id.action_fragmentone_to_fragmenttwo) }Copy the code

We can write the action out of the hierarchy so that all pages in the navigation can jump to the page specified by the action. This defines the global action. \

We can learn through the Navigation above. FindNavController (mRoot!! .navigate(R.i.d.action_fragmentone_to_fragmenttwo) to perform a jump. We find that the jump is mainly done through the NavController, and there are several ways to get the NavController: Kotlin:

  • Fragment.findNavController()
  • View.findNavController()
  • Activity.findNavController(viewId: Int)

Java way:

  • NavHostFragment.findNavController(Fragment)
  • Navigation.findNavController(Activity, @IdRes int viewId)
  • Navigation.findNavController(View)

For example, our jump example above could also be written as

 findNavController().navigate(R.id.action_fragmentone_to_fragmenttwo)
 / / ormRoot!! .findNavController().navigate(R.id.action_fragmentone_to_fragmenttwo)Copy the code

If we add Safe Args, we can also use Safe Args for type-safe jumps to generate a class for each destination of the build operation. The generated class name adds “Directions” to the source destination class name. For example, if we have a FragmentOne jump to FragmentTwo here and our source destination name is FragmentOne, the name of the generated class is FragmentOneDirections. So our jump code above could also be written as

valaction = FragmentOneDirections.actionFragmentoneToFragmenttwo() Navigation.findNavController(mRoot!!) .navigate(action)Copy the code

This is a type-safe jump.

1.6 Using DeepLinkRequest navigation

You can navigate directly to implicit deep link destinations using Scheme with navigate(NavDeepLinkRequest), or custom urls. The code is as follows:

<? xml version="1.0" encoding="utf-8"? > <navigation 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/nav_graph"
    app:startDestination="@+id/fragmentOne">

    <fragment
        android:id="@+id/fragmentOne"
        android:name="com.example.jetpackdatabindingtestapp.ui.navigation.FragmentOne"
        android:label="fragment_one"
        tools:layout="@layout/fragment_one">
    </fragment>

    <activity
        android:id="@+id/order_activity"
        android:name="com.example.jetpackdatabindingtestapp.ui.navigation.OrderActivity"
        android:label="order_activity"
        tools:layout="@layout/activity_order">
        <deepLink app:uri="www.ccm.com/order"/>
    </activity>

</navigation>

// Jump to the listener event for OrderActivity
tvEnterOrder.setOnClickListener {
   val request = NavDeepLinkRequest.Builder.fromUri("http://www.ccm.com/order".toUri()).build()
   findNavController().navigate(request)
}
Copy the code
  • Define a FragmentOne, an OrderActivity, and an OrderActivity with a deepLink specified
  • Deeplink uses the app: URI property to specify urIs
  • Perform the jump to OrderActivity in FragmentOne when tvEnterOrder is clicked
  • Val request = NavDeepLinkRequest. Builder. FromUri (” www.ccm.com/order “. ToUr…
  • FindNavController ().navigate(request) To navigate through the request

The scheme specified for OrderActivity under AndroidMainfest.xml is as follows:

 <activity android:name=".ui.navigation.OrderActivity">
    <intent-filter>
        <action android:name="android.intent.action.VIEW"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <category android:name="android.intent.category.BROWSABLE"/>
        <data android:scheme="https"/>
        <data android:scheme="http"/>
        <data android:host="www.ccm.com"/>
        <data android:pathPrefix="/order/"/>
    </intent-filter>
</activity>
Copy the code

That’s how deepLink works.

1.7 Adding transition Animations

Add a transition animation to a jump. Nav_graph.xml:

<? xml version="1.0" encoding="utf-8"? > <navigation 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/nav_graph"
    app:startDestination="@+id/fragmentOne">

    <fragment
        android:id="@+id/fragmentOne"
        android:name="com.example.jetpackdatabindingtestapp.ui.navigation.FragmentOne"
        android:label="fragment_one"
        tools:layout="@layout/fragment_one">
        <action
            app:popEnterAnim="@anim/fade_in"
            app:popExitAnim="@anim/fade_out"
            app:exitAnim="@anim/bottom_out"
            app:enterAnim="@anim/bottom_in"
            android:id="@+id/action_fragmentone_to_fragmenttwo"
            app:destination="@+id/fragmentTwo"/>
    </fragment>

    <fragment
        android:id="@+id/fragmentTwo"
        android:name="com.example.jetpackdatabindingtestapp.ui.navigation.FragmentTwo"
        android:label="fragment_two"
        tools:layout="@layout/fragment_two">
    </fragment>

</navigation>
Copy the code
  • App :popEnterAnim and App :popExitAnim are defined to jump back to the page animation. For example, here we’re going from FragmentTwo back to FragmentOne, and FragmentOne appears as fading in
  • App :enterAnim and App :exitAnim are animations that define jumps to other pages, such as the animation performed by FragmentOne when it jumps from FragmentOne to FragmentTwo

1.8 Nested navigation charts

For our navigation diagrams (and here nav_graph.xml), add nested navigation diagrams. For example, if we add a login navigation diagram to nav_graph.xml, it looks like this:

<? xml version="1.0" encoding="utf-8"? > <navigation 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/nav_graph"
    app:startDestination="@+id/fragmentOne">

    <fragment
        android:id="@+id/fragmentOne"
        android:name="com.example.jetpackdatabindingtestapp.ui.navigation.FragmentOne"
        android:label="fragment_one"
        tools:layout="@layout/fragment_one">
        <action
            app:popEnterAnim="@anim/fade_in"
            app:popExitAnim="@anim/fade_out"
            app:exitAnim="@anim/bottom_out"
            app:enterAnim="@anim/bottom_in"
            android:id="@+id/action_fragmentone_to_fragmenttwo"
            app:destination="@+id/fragmentTwo"/>
    </fragment>

    <fragment
        android:id="@+id/fragmentTwo"
        android:name="com.example.jetpackdatabindingtestapp.ui.navigation.FragmentTwo"
        android:label="fragment_two"
        tools:layout="@layout/fragment_two">
        <action
            android:id="@+id/action_fragmenttwo_to_logingraph"
            app:destination="@+id/login_graph"/>
    </fragment>

    <navigation android:id="@+id/login_graph" app:startDestination="@+id/fragmentLogin">

        <fragment
            android:id="@+id/fragmentLogin"
            android:name="com.example.jetpackdatabindingtestapp.ui.navigation.FragmentLogin"
            android:label="fragment_login"
            tools:layout="@layout/fragment_login">
            <action
                android:id="@+id/action_fragmentlogin_to_fragmentregist"
                app:destination="@+id/fragmentRegist"/>
        </fragment>

        <fragment
            android:id="@+id/fragmentRegist"
            android:name="com.example.jetpackdatabindingtestapp.ui.navigation.FragmentRegist"
            android:label="fragment_regist"
            tools:layout="@layout/fragment_regist">
        </fragment>

    </navigation>

</navigation>
Copy the code
  • Its ID is login_graph, and its starting destination is the login page fragmentLogin.
  • The login navigation contains a login page, fragmentLogin, and a login page, fragmentRegist, which has an action that jumps to the login page.
  • FragmentTwo can be clicked to jump to the login section

Currently we can also pull out the navigation diagram of the login and refer to it as an include. This allows the navigation diagram of the login process to be referenced wherever needed. We create a login_graph.xml file under res->navigation. The code is as follows:

<? xml version="1.0" encoding="utf-8"? > <navigation 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:id="@+id/login_graph"
    app:startDestination="@+id/fragmentLogin">

    <fragment
        android:id="@+id/fragmentLogin"
        android:name="com.example.jetpackdatabindingtestapp.ui.navigation.FragmentLogin"
        tools:layout="@layout/fragment_login"
        android:label="fragment_login">
        <action
            android:id="@+id/action_fragmentlogin_to_fragmentregist"
            app:destination="@+id/fragmentRegist" />
    </fragment>

    <fragment
        android:id="@+id/fragmentRegist"
        android:name="com.example.jetpackdatabindingtestapp.ui.navigation.FragmentRegist"
        tools:layout="@layout/fragment_regist"
        android:label="fragment_regist"></fragment>

</navigation>
Copy the code

Then we can include the navigation graph login_graph.xml in nav_graph.xml. The code is as follows:

<? xml version="1.0" encoding="utf-8"? > <navigation 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/nav_graph"
    app:startDestination="@+id/fragmentOne">

    <fragment
        android:id="@+id/fragmentOne"
        android:name="com.example.jetpackdatabindingtestapp.ui.navigation.FragmentOne"
        android:label="fragment_one"
        tools:layout="@layout/fragment_one">
        <action
            app:popEnterAnim="@anim/fade_in"
            app:popExitAnim="@anim/fade_out"
            app:exitAnim="@anim/bottom_out"
            app:enterAnim="@anim/bottom_in"
            android:id="@+id/action_fragmentone_to_fragmenttwo"
            app:destination="@+id/fragmentTwo"/>
    </fragment>

    <fragment
        android:id="@+id/fragmentTwo"
        android:name="com.example.jetpackdatabindingtestapp.ui.navigation.FragmentTwo"
        android:label="fragment_two"
        tools:layout="@layout/fragment_two">
        <action
            android:id="@+id/action_fragmenttwo_to_logingraph"
            app:destination="@+id/login_graph"/>
    </fragment>

    <include app:graph="@navigation/login_graph"/>

</navigation>
Copy the code

<include app:graph=”@navigation/login_graph”/> Use app:graph to reference our login_graph login navigation graph. The other logic stays the same.

1.9 Transferring Parameters

When we jump to a page, we often need to pass some parameters. Navigation is also supported, although in general it is strongly recommended that you only pass a minimal amount of data between destinations rather than a large amount of data

1.9.1 Define Parameters in the Navigation Diagram

We can use argument to add jump arguments to the navigation diagram. For example, we pass name and age arguments to FragmentTwo. The code is as follows:

<? xml version="1.0" encoding="utf-8"? > <navigation 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/nav_graph"
    app:startDestination="@+id/fragmentOne">

    <fragment
        android:id="@+id/fragmentOne"
        android:name="com.example.jetpackdatabindingtestapp.ui.navigation.FragmentOne"
        android:label="fragment_one"
        tools:layout="@layout/fragment_one">
        <action
            android:id="@+id/action_fragmentone_to_fragmenttwo"
            app:destination="@+id/fragmentTwo"/>
    </fragment>

    <fragment
        android:id="@+id/fragmentTwo"
        android:name="com.example.jetpackdatabindingtestapp.ui.navigation.FragmentTwo"
        android:label="fragment_two"
        tools:layout="@layout/fragment_two">

        <argument android:name="name"
            app:argType="string"
            android:defaultValue="old man"/>

        <argument android:name="age"
            app:argType="string"
            android:defaultValue="11"/>

    </fragment>

</navigation>


// There is a button in FragmentOne to switch to FragmentTwotvClickEnterTwo? .setOnClickListener{ findNavController().navigate(R.id.action_fragmentone_to_fragmenttwo) }Copy the code
  • Argument is used to add arguments to pass
  • Android :name=”name” indicates the name of the passed parameter
  • App :argType indicates the type of argument passed
  • Android :defaultValue indicates the defaultValue of the passed argument

The Navigation library supports the following parameter types:

type App: argType syntax Whether the default value is supported Are null values supported?
The integer app:argType=”integer” is no
Floating point Numbers app:argType=”float” is no
Long integer app:argType=”long” Yes – The default value must always end with an “L” suffix (for example, “123L”). no
Boolean value app:argType=”boolean” Is the “true” or “false” no
string app:argType=”string” is is
The resource reference app:argType=”reference” Is: the default value must be a “@ resourceType/resourceName” format (for example, “@ style/myCustomStyle”) or “0” no
Custom Parcelable App :argType=”<type>”, where <type> is the fully qualified class name for Parcelable The default value @null is supported. No other default values are supported. is
Custom Serializable App :argType=”<type>”, where <type> is the fully qualified class name of Serializable The default value @null is supported. No other default values are supported. is
Custom Enum App :argType=”<type>”, where <type> is the fully qualified name of Enum Yes – The default value must match the unqualified name (for example, “SUCCESS” matches MyEnum.SUCCESS). no

If the parameter type supports NULL, you can declare the default null using Android :defaultValue=” @NULL”

We usually use the argument argument in the destination. For example, the argument under the fragment above. And when we have a jump action (or operation) under the transfer parameter, then need to take precedence over the operation. Such as:

<? xml version="1.0" encoding="utf-8"? > <navigation 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/nav_graph"
    app:startDestination="@+id/fragmentOne">
    <fragment
        android:id="@+id/fragmentOne"
        android:name="com.example.jetpackdatabindingtestapp.ui.navigation.FragmentOne"
        android:label="fragment_one"
        tools:layout="@layout/fragment_one">
         <action
            android:id="@+id/action_fragmentone_to_fragmenttwo"
            app:destination="@+id/fragmentTwo">

            <argument android:name="name"
                app:argType="string"
                android:defaultValue="action name old man"/>

            <argument android:name="age"
                app:argType="string"
                android:defaultValue="action age 11"/>
        </action>
    </fragment>

    <fragment
        android:id="@+id/fragmentTwo"
        android:name="com.example.jetpackdatabindingtestapp.ui.navigation.FragmentTwo"
        android:label="fragment_two"
        tools:layout="@layout/fragment_two">
        
        <argument android:name="name"
            app:argType="string"
            android:defaultValue="old man"/>
            
        <argument android:name="age"
            app:argType="string"
            android:defaultValue="11"/>
    </fragment>
</navigation>
Copy the code

For example, in this example, the FragmentOne jump to the FragmentTwo action has its argument. The argument under FragmentTwo itself also carries arguments. In this case, we will take the action as the priority. And under priority operation > destination underground

1.9.2 Passing Parameters using bundle

For example, in the FragmentOne example, pass a name and an age to FragmentTwo. FragmentTwo displays the passed content on the text. The code is as follows:

// FragmentOne's code
class FragmentOne :Fragment() {private varmRoot:View? =null
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup? , savedInstanceState:Bundle?).: View? {
        mRoot = inflater.inflate(R.layout.fragment_one,container,false)
        valtvClickEnterTwo = mRoot? .findViewById<View>(R.id.tv_click_enter_two) tvClickEnterTwo? .setOnClickListener{val bundle = bundleOf("name" to "chencm"."age" to "11") Navigation.findNavController(mRoot!!) .navigate(R.id.action_fragmentone_to_fragmenttwo,bundle) }return mRoot
    }
}

// FragmentTwo's code
class FragmentTwo : Fragment() {private varmRoot: View? =null
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup? , savedInstanceState:Bundle?).: View? {
        mRoot = inflater.inflate(R.layout.fragment_two,container,false)
        valname = arguments? .getString("name")? :""
        valage = arguments? .getString("age")? :""
        valtv_text = mRoot? .findViewById<TextView>(R.id.tv_text) tv_text? .text ="name===${name}==age===${age}"
        return mRoot
    }
}
Copy the code
1.9.3 Using Safe Args to deliver secure data

If we use the Safe Args plug-in, we can use Safe Args to pass secure data. Again, we need to define the argument in the navigation diagram

<? xml version="1.0" encoding="utf-8"? > <navigation 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/nav_graph"
    app:startDestination="@+id/fragmentOne">
    <fragment
        android:id="@+id/fragmentOne"
        android:name="com.example.jetpackdatabindingtestapp.ui.navigation.FragmentOne"
        android:label="fragment_one"
        tools:layout="@layout/fragment_one">
         <action
            android:id="@+id/action_fragmentone_to_fragmenttwo"
            app:destination="@+id/fragmentTwo"/>
    </fragment>

    <fragment
        android:id="@+id/fragmentTwo"
        android:name="com.example.jetpackdatabindingtestapp.ui.navigation.FragmentTwo"
        android:label="fragment_two"
        tools:layout="@layout/fragment_two">
        
        <argument android:name="name"
            app:argType="string"
            android:defaultValue="old man"/>
            
        <argument android:name="age"
            app:argType="string"
            android:defaultValue="11"/>
    </fragment>
</navigation>
Copy the code

Click on the FragmentOne button to jump to FragmentTwo. Let’s take a look at how to use Safe Args to pass secure data:

tvClickEnterTwo? .setOnClickListener{ findNavController().navigate(FragmentOneDirections.actionFragmentoneToFragmenttwo(name ="ccm",age = "123"))}Copy the code

We talked about above Safe Args will automatically create a class Directions for each destination, and the corresponding action id will be generated a method actionFragmentoneToFragmenttwo (), and the argument will be as a method of parameters passed in. And that’s where it goes. We can use arguments to receive messages as follows:

class FragmentTwo : Fragment() {private varmRoot: View? =null
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup? , savedInstanceState:Bundle?).: View? {
        mRoot = inflater.inflate(R.layout.fragment_two,container,false)
        valname = arguments? .getString("name")? :""
        valage = arguments? .getString("age")? :""
        valtv_text = mRoot? .findViewById<TextView>(R.id.tv_text) tv_text? .text ="name===${name}==age===${age}"tv_text? .setOnClickListener { Navigation.findNavController(mRoot!!) .navigate(R.id.action_fragmenttwo_to_logingraph) }return mRoot
    }
}
Copy the code

arguments? .getString(“name”) gets data by getArguments().

1.9.4 Navigating and returning to the stack

Android maintains a return stack that contains the destinations you’ve previously visited. When the user opens your application, the application’s first destination is placed on the stack. Each call to the navigate() method puts another destination at the top of the stack. Click the up or return will call NavController respectively. NavigateUp () and NavController popBackStack () method, Used to remove (or pop-up) on top of the stack NavController destination. PopBackStack () returns a Boolean value that indicates that it is on a return to the destination successfully. If this method returns false, it is at the top of the stack. On clicking the back button, the page is typically processed as Finish.

if(! navController.popBackStack()) {// Call finish() on your Activity
    finish()
}
Copy the code
1.9.5 popUpTo and popUpToInclusive

We often have scenarios where A jumps to B, B jumps to C, and C wants to jump back to A. With each navigation operation, a destination is added to the return stack. If you were to navigate repeatedly through this process, your return stack would contain multiple collections containing each destination (for example, A, B, C, A, and so on). To avoid this duplication, you can specify app:popUpTo and app:popUpToInclusive in the operation from destination C to destination A, as shown in the following example:

<? xml version="1.0" encoding="utf-8"? > <navigation 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/nav_graph"
    app:startDestination="@+id/fragmentA">

    <fragment
        android:id="@+id/fragmentA"
        android:name="com.example.jetpackdatabindingtestapp.ui.navigation.FragmentA"
        android:label="fragment_a"
        tools:layout="@layout/fragment_a">
        <action
            android:id="@+id/action_a_to_b"
            app:destination="@+id/fragmentB">
        </action>
    </fragment>

    <fragment
        android:id="@+id/fragmentB"
        android:name="com.example.jetpackdatabindingtestapp.ui.navigation.FragmentB"
        android:label="fragment_b"
        tools:layout="@layout/fragment_b">
        
		<action
            android:id="@+id/action_b_to_c"
            app:destination="@+id/fragmentC">
        </action>

    </fragment>

	<fragment
        android:id="@+id/fragmentC"
        android:name="com.example.jetpackdatabindingtestapp.ui.navigation.FragmentC"
        tools:layout="@layout/fragment_c"
        android:label="fragment_c">

        <action
            android:id="@+id/action_c_to_a"
            app:destination="@+id/fragmentA"
            app:popUpTo="@+id/fragmentA"
            app:popUpToInclusive="true"
            />
    </fragment>
    
</navigation>
Copy the code

An action for FragmentA jumps to FragmentB, an action for FragmentB jumps to FragmentC, and an action for C jumps back to FragmentA.

  • App :popUpTo means navigation to A, and we remove B and C from the stack during navigation
  • App :popUpToInclusive=true means we’ll also pop the first A off the stack. Note that if you do not use app:popUpToInclusive, the return stack contains two instances of destination A.

Ii: The structure of Navigation

Above, we learned the use of Navigation. By using Navigation, we can summarize what parts Navigation consists of. The navigation component consists of three key parts

  • Navigation diagram: This is the nav_graph.xml file we wrote, which we call the navigation diagram
  • NavHost: Empty container to display the target in the navigation diagram. The navigation component contains a default NavHost implementation (NavHostFragment). We have specified in the use of the use of the android: name = “androidx. Navigation. Fragments. NavHostFragment”
  • NavController: Manages the object navigated by the application in NavHost. It mainly controls the jump switch before navigation

Navigation components provide a variety of other advantages:

  • Process Fragment transactions.
  • By default, round-trip operations are handled correctly.
  • Provides standardized resources for animations and transformations. (Page transition animation)
  • Implement and handle deep linking. (deeplink)
  • Including navigation interface modes (such as drawer navigation and bottom navigation), users need to do very little extra work
  • Safe Args – Gradle plug-in that provides type safety when navigating and passing data between targets
  • ViewModel support – You can limit the scope of a ViewModel to a navigation diagram to share data related to the interface between the targets of the diagram