【Jetpack】Navigation navigation component② (Navigation core points description | Create Navigation Graph | Create NavHostFragment | Complete code example )


Code address:





1. Description of the core points of Navigation navigation component development




1. The creation order of each sub-component of Navigation


The main points of the creation order of each subcomponent of the Navigation navigation component are as follows:

  • First, create the navigated Fragment page code and the corresponding layout file;
  • Then, create a corresponding Navigation Graph based on the created Fragment , and configure the jump action between Fragments in it;
  • Then, create a NavHostFragment component that displays content based on the created Navigation Graph ;
  • Finally, get the NavController component in the Activity to realize the jump between Fragments;

It must be created according to the above process: Fragment -> Navigation Graph -> NavHostFragment -> NavController , the latter components depend on the previous components, otherwise the Navigation navigation cannot be realized;


2. Import Navigation dependencies


To use the Navigation component, you must import Navigation dependencies, and different development languages ​​import different dependencies:

  • Use the Java language to develop Navigation navigation, and import the following dependencies:
dependencies {
    
      
    implementation 'androidx.navigation:navigation-fragment:2.2.2'
    implementation 'androidx.navigation:navigation-ui:2.2.2'
}
  • Use Kotlin language to develop Navigation navigation, and import the following dependencies:
dependencies {
    
      
    implementation 'androidx.navigation:navigation-fragment-ktx:2.3.0'  
    implementation 'androidx.navigation:navigation-ui-ktx:2.3.0'  
}

If you do not import dependencies and use Navigation directly, a "failed to add navigation dependency" exception message will be reported;


3. Create Fragment and layout files


Right-click the code package to create a Fragment, select the "New / Fragment / Fragment (Blank)" option , you can directly create a Fragment, and generate the corresponding Fragment layout file;

insert image description here


4. Create Navigation Graph


Right-click the res resource directory, and in the pop-up drop-down menu, select the "New / Android Resource File" option,

insert image description here
In the "Resource Type" option, select the "Navigation" option. After selection, the "Root element" and "Directory name" options will be automatically set. Developers only need to set a "File name";

insert image description here
When creating a Navigation Graph, you need to specify which Fragments to include in navigation management, which is why you need to create a Fragment before creating a Navigation Graph;

After creating the Navigation Graph, in the Design mode, click the "New Destination" button to add the Fragment page to be navigated, where both FragmentA and FragmentB are included in the Navigation navigation management;

insert image description here

After creation, you can drag the mouse to set the jump relationship between the two Fragments in the Navigation Graph, FragmentA jumps to FragmentB, and FragmentB jumps to FragmentA;

insert image description here

In this way, the creation of the Navigation Graph is completed, and then the above two jumps will be called through the NavController to realize the jump between the two Fragments respectively;


5. Create NavHostFragment


NavHostFragment is set in the layout file of the Activity,<fragment/> generally a android:name="androidx.navigation.fragment.NavHostFragment"property is set for the label, and the fragment becomes NavHostFragment;

    <fragment
        android:id="@+id/fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:defaultNavHost="true"
        app:navGraph="@navigation/navigation_graph" />

It is not recommended to drag the NavHostFragment under the Container to the layout in the Design graphical interface, the generated code is wrong;

The specific error content is analyzed in detail in the error record column, and will not be repeated here;
insert image description here


6. Create NavController


Get the NavController by calling the findNavController function in the Activity , and then navigate through the NavController variable;

The management operation of fragmentContainerView component is done through NavController;

        // fragmentContainerView 组件的 管理 操作通过 NavController 完成
        // 对应的就是 navController 实例变量
        val navController = findNavController(this, R.id.fragment)
        NavigationUI.setupActionBarWithNavController(this, navController)

7. Fragment realizes navigation operation


In the Fragment interface, jump to another Fragment interface by clicking the button;

First, get the NavigationController, and get the NavigationController instance object by calling the Navigation.findNavController function ;

Then, call NavigationController#navigate to navigate, and pass in the id of the specific action in the Navigation Graph;

            // 获取 NavigationController
            val navController = Navigation.findNavController(it)
            // 按照 action_fragmentA_to_fragmentB 对应的 action 的导航路线走
            navController.navigate(R.id.action_fragmentA_to_fragmentB)

R.id.action_fragmentA_to_fragmentBThe corresponding action in the above code is as follows:

    <fragment
        android:id="@+id/fragmentA"
        android:name="kim.hsl.nav.FragmentA"
        android:label="fragment_a"
        tools:layout="@layout/fragment_a" >
        <action
            android:id="@+id/action_fragmentA_to_fragmentB"
            app:destination="@id/fragmentB" />
    </fragment>




2. Complete code example of Navigation navigation component



Code address:


1. Fragment complete source code


Create 2 Fragments, set a button for each Fragment, and jump between the two Fragments;

FragmentA source code

The core jump source code in Fragment is as follows, first get NavigationController, and then call NavigationController#navigate to jump to FragmentB page;

            // 获取 NavigationController
            val navController = Navigation.findNavController(it)
            // 按照 action_fragmentA_to_fragmentB 对应的 action 的导航路线走
            navController.navigate(R.id.action_fragmentA_to_fragmentB)

Complete source code:

package kim.hsl.nav

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import androidx.fragment.app.Fragment
import androidx.navigation.Navigation
import androidx.navigation.Navigation.findNavController

// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"

/**
 * A simple [Fragment] subclass.
 * Use the [FragmentA.newInstance] factory method to
 * create an instance of this fragment.
 */
class FragmentA : Fragment() {
    
    
    // TODO: Rename and change types of parameters
    private var param1: String? = null
    private var param2: String? = null

    override fun onCreate(savedInstanceState: Bundle?) {
    
    
        super.onCreate(savedInstanceState)
        arguments?.let {
    
    
            param1 = it.getString(ARG_PARAM1)
            param2 = it.getString(ARG_PARAM2)
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
    
    
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_a, container, false)
    }

    companion object {
    
    
        /**
         * Use this factory method to create a new instance of
         * this fragment using the provided parameters.
         *
         * @param param1 Parameter 1.
         * @param param2 Parameter 2.
         * @return A new instance of fragment FragmentA.
         */
        // TODO: Rename and change types and number of parameters
        @JvmStatic
        fun newInstance(param1: String, param2: String) =
            FragmentA().apply {
    
    
                arguments = Bundle().apply {
    
    
                    putString(ARG_PARAM1, param1)
                    putString(ARG_PARAM2, param2)
                }
            }
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    
    
        super.onViewCreated(view, savedInstanceState)
        val button = view.findViewById<Button>(R.id.button)
        button.setOnClickListener {
    
    
            // 获取 NavigationController
            val navController = Navigation.findNavController(it)
            // 按照 action_fragmentA_to_fragmentB 对应的 action 的导航路线走
            navController.navigate(R.id.action_fragmentA_to_fragmentB)
        }
    }
}

FragmentA layout file

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".FragmentA">

    <!-- TODO: Update blank fragment layout -->
    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="@string/hello_blank_fragment" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="跳转到 B"
        android:onClick="onClick" />

</FrameLayout>

FragmentB source code

The core jump source code in Fragment is as follows, first get NavigationController, and then call NavigationController#navigate to jump to FragmentB page;

            // 获取 NavigationController
            val navController = Navigation.findNavController(it)
            // 按照 action_fragmentB_to_fragmentA 对应的 action 的导航路线走
            navController.navigate(R.id.action_fragmentB_to_fragmentA)

The complete code is as follows:

package kim.hsl.nav

import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import androidx.navigation.Navigation

// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"

/**
 * A simple [Fragment] subclass.
 * Use the [FragmentB.newInstance] factory method to
 * create an instance of this fragment.
 */
class FragmentB : Fragment() {
    
    
    // TODO: Rename and change types of parameters
    private var param1: String? = null
    private var param2: String? = null

    override fun onCreate(savedInstanceState: Bundle?) {
    
    
        super.onCreate(savedInstanceState)
        arguments?.let {
    
    
            param1 = it.getString(ARG_PARAM1)
            param2 = it.getString(ARG_PARAM2)
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
    
    
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_b, container, false)
    }

    companion object {
    
    
        /**
         * Use this factory method to create a new instance of
         * this fragment using the provided parameters.
         *
         * @param param1 Parameter 1.
         * @param param2 Parameter 2.
         * @return A new instance of fragment FragmentB.
         */
        // TODO: Rename and change types and number of parameters
        @JvmStatic
        fun newInstance(param1: String, param2: String) =
            FragmentB().apply {
    
    
                arguments = Bundle().apply {
    
    
                    putString(ARG_PARAM1, param1)
                    putString(ARG_PARAM2, param2)
                }
            }
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    
    
        super.onViewCreated(view, savedInstanceState)
        val button = view.findViewById<Button>(R.id.button)
        button.setOnClickListener {
    
    
            // 获取 NavigationController
            val navController = Navigation.findNavController(it)
            // 按照 action_fragmentB_to_fragmentA 对应的 action 的导航路线走
            navController.navigate(R.id.action_fragmentB_to_fragmentA)
        }
    }
}

FragmentB layout file

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".FragmentB">

    <!-- TODO: Update blank fragment layout -->
    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="@string/hello_blank_fragment" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="跳转到 A"
        android:onClick="onClick" />

</FrameLayout>

2. Navigation Graph source code


Create a Navigation Graph, import two Fragments, and set the jump relationship between the two Fragments in the Navigation Graph, FragmentA jumps to FragmentB, and FragmentB jumps to FragmentA;

<?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/navigation_graph"
    app:startDestination="@id/fragmentA">

    <fragment
        android:id="@+id/fragmentA"
        android:name="kim.hsl.nav.FragmentA"
        android:label="fragment_a"
        tools:layout="@layout/fragment_a" >
        <action
            android:id="@+id/action_fragmentA_to_fragmentB"
            app:destination="@id/fragmentB" />
    </fragment>
    <fragment
        android:id="@+id/fragmentB"
        android:name="kim.hsl.nav.FragmentB"
        android:label="fragment_b"
        tools:layout="@layout/fragment_b" >
        <action
            android:id="@+id/action_fragmentB_to_fragmentA"
            app:destination="@id/fragmentA" />
    </fragment>
</navigation>

3. Add the NavHostFragment component to the Activity layout file


NavHostFragment is set in the layout file of the Activity, <fragment/>generally a android:name="androidx.navigation.fragment.NavHostFragment"property is set for the label, and the fragment becomes NavHostFragment;

    <fragment
        android:id="@+id/fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:defaultNavHost="true"
        app:navGraph="@navigation/navigation_graph" />

The complete layout file code is as follows:

<?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=".MainActivity">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <fragment
        android:id="@+id/fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:defaultNavHost="true"
        app:navGraph="@navigation/navigation_graph" />

</androidx.constraintlayout.widget.ConstraintLayout>

4. Get NavController in the Activity code and navigate


Get the NavController by calling the findNavController function in the Activity, and then navigate through the NavController variable;

The management operation of fragmentContainerView component is done through NavController;

        // fragmentContainerView 组件的 管理 操作通过 NavController 完成
        // 对应的就是 navController 实例变量
        val navController = findNavController(this, R.id.fragment)
        NavigationUI.setupActionBarWithNavController(this, navController)

The complete code is as follows:

package kim.hsl.nav

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.Navigation.findNavController
import androidx.navigation.ui.NavigationUI

class MainActivity : AppCompatActivity() {
    
    
    override fun onCreate(savedInstanceState: Bundle?) {
    
    
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // fragmentContainerView 组件的 管理 操作通过 NavController 完成
        // 对应的就是 navController 实例变量
        val navController = findNavController(this, R.id.fragment)
        NavigationUI.setupActionBarWithNavController(this, navController)
    }
}

5. Operation effect


Click the button on the FragmentA page to jump to the FragmentB page, click the button on the FragmentB page to jump to the FragmentA page;

Please add a picture description


Code address:

Guess you like

Origin blog.csdn.net/han1202012/article/details/131299078
Recommended