The author
Hello everyone, my name is Xiaoqi;
I graduated from The Software Engineering major of Central South University of Forestry and Technology in 2016. After graduation, I did Android development in the education industry. Later, I joined the Android team of 37 Mobile Games in October, 2016.
At present, I am mainly responsible for the development related to the domestic release of Android, while taking into account the development of several internal apps.
directory
-
Navigation — Introduction (this chapter)
-
Navigation – advanced
-
Navigation
preface
In daily development, an activity with multiple fragments is increasingly used. A typical example is the home page of an app, which is usually composed of an activity+ multiple sub-tabs. That for Fragment display, hide and so on we are usually managed by FragmentManager, but this way is easy to cause code bloat, difficult to maintain.
With Jetpack’s Navigation component, Navigation, you can easily manage switching between fragments, making development much easier.
Three elements
Navigation graph
An XML resource that contains all navigation-related information
NavHostFragment
A special Fragment used as a container for navigation content
NavController
Manage navigation objects and hop between fragments
The basic use
Introduction of depend on
implementation 'androidx. Navigation: navigation - fragments - KTX: 2.3.1'
implementation 'androidx. Navigation: navigation - UI - KTX: 2.3.1'
Copy the code
Creating a navigation view
First make sure AndroidStudio is above 3.3
1. Right-click Res and click New -> Android Resource Directory
2. In the second row of the panel that appears, select Navigation from the Resource Type drop-down list, and then click OK
3. Add a navigation directory to the res directory. Right-click the directory and click New -> Navigation Resource File. A nav_graph.xml is created.
Configuration graph
Go to design mode, click the plus sign at 2, and select Create New Destination to quickly Create a new Fragment. Here we create FragmentA, FragmentB, and FragmentC
Built, you can manually configure the jump between the pages, click a page, the right side will appear a dot, drag dot point to jump to the page, here set the jump relationship for FragmentA -> FragmentB -> FragmentC.
Switch to the Code bar and you can see the following Code generated
<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.testnavigation.FragmentA"
android:label="fragment_a"
tools:layout="@layout/fragment_a" >
<action
android:id="@+id/action_fragmentA_to_fragmentB2"
app:destination="@id/fragmentB" />
</fragment>
<fragment
android:id="@+id/fragmentB"
android:name="com.example.testnavigation.FragmentB"
android:label="fragment_b"
tools:layout="@layout/fragment_b" >
<action
android:id="@+id/action_fragmentB_to_fragmentC2"
app:destination="@id/fragmentC" />
</fragment>
<fragment
android:id="@+id/fragmentC"
android:name="com.example.testnavigation.FragmentC"
android:label="fragment_c"
tools:layout="@layout/fragment_c" />
</navigation>
Copy the code
- Navigation is the root TAB, and the first page to launch by default is configured with startDestination, where FragmentA is configured
- The fragment tag represents a fragment. You can configure not only the fragment, you can also configure the activity, and you can even customize it (we’ll talk about that later).
- The Action TAB defines the behavior of the page jump, equivalent to each line in the picture above, destination defines the target page of the jump, and can define the animation of the jump, and so on
Add NavHostFragment
Configure NavHostFragment in the layout file of MainActivity
<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">
<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:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/nav_graph" />
</androidx.constraintlayout.widget.ConstraintLayout>
Copy the code
- The android: name specified NavHostFragment
- App :navGraph specifies the navigation view, which is built as nav_graph.xml
- App :defaultNavHost=true means that the system can intercept the return key of the fragment. If you press the return key in the fragment during the hop process, You can make the fragment go back to the previous page just like the activity
Now we can run the application and see the FragmentA display page. This is because the Layout file of the MainActivity has NavHostFragment configured and NavHostFragment is given a navigation view. The navigation view specifies the default display of FragmentA with startDestination.
Navigation between fragments is managed by NavController
If you want to jump to a FragmentA -> FragmentB -> FragmentC, if you want to jump to a FragmentB, if you want to jump to a NavController, if you want to jump to a FragmentB, if you want to jump to a NavController, you want to jump to a NavController
Open the FragmentA class and define a click event for the TextView in the layout
override fun onViewCreated(view: View, savedInstanceState: Bundle?). {
super.onViewCreated(view, savedInstanceState)
tv.setOnClickListener {
val navController = Navigation.findNavController(it)
navController.navigate(R.id.action_fragmentA_to_fragmentB2)
}
}
Copy the code
If you find that the layout file cannot be imported automatically, you should add the plugin ‘kotlin-Android-extensions’ to app.build.
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
Copy the code
Changed since AndroidStudio4.1
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-android-extensions'
}
Copy the code
As you can see, navigating the fragment through navController is as simple as taking the navController object and calling its navigate method, passing in the ID of the action defined earlier in the NAV_graph.
In the same way, set a click event for the TextView in FragmentB to jump to FragmentC when clicked
If you set defaultNavHost to false, press the back key to return to the desktop. If you set defaultNavHost to false, press the back key to return to the desktop. Now you see what the app:defaultNavHost property means.
More usage
In addition to setting the target page, the action property can also set animation, page to page parameter passing, fragment back stack management, and so on
animation
-
EnterAnim: Target page animation when jumping
-
ExitAnim: Animation of the original page when jumping
-
PopEnterAnim: Target page animation during rollback
-
PopExitAnim: Animation of the original page on rollback
After configuring the animation, you will find that the action has four more animation-related properties
<fragment
android:id="@+id/fragmentA"
android:name="com.example.testnavigation.FragmentA"
android:label="fragment_a"
tools:layout="@layout/fragment_a" >
<action
android:id="@+id/action_fragmentA_to_fragmentB2"
app:destination="@id/fragmentB"
app:enterAnim="@anim/enter_in"
app:exitAnim="@anim/enter_out"
app:popEnterAnim="@anim/exit_in"
app:popExitAnim="@anim/exit_out" />
</fragment>
Copy the code
parameter
The above example shows jumping between fragments, but parameter passing is also possible.
override fun onViewCreated(view: View, savedInstanceState: Bundle?). {
super.onViewCreated(view, savedInstanceState)
tv.setOnClickListener {
val navController = Navigation.findNavController(it)
val bundle = Bundle()
bundle.putString("key"."test")
navController.navigate(R.id.action_fragmentA_to_fragmentB2, bundle)
}
}
Copy the code
It is recommended to use Google’s official safeArgs for parameter passing. Compared with the traditional method of passing parameters, safeArgs has the advantages of safe parameter types, and with the support of Google’s official, it is very convenient to pass parameter values.
Add the plugin under build.gradle at the root of your project
classpath "Androidx. Navigation: navigation - safe - the args - gradle - plugin: 2.3.1." "
Copy the code
buildscript {
ext.kotlin_version = "1.3.72"
repositories {
google()
jcenter()
}
dependencies {
classpath "Com. Android. Tools. Build: gradle: 4.4.1." "
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "Androidx. Navigation: navigation - safe - the args - gradle - plugin: 2.3.1." "
}
}
allprojects {
repositories {
google()
jcenter()
}
}
Copy the code
Then in the build of the app. Gradle referenced in the ‘androidx. Navigation. Safeargs. Kotlin’
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'androidx.navigation.safeargs.kotlin'
Copy the code
After AS4.1:
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-android-extensions'
id 'androidx.navigation.safeargs.kotlin'
}
Copy the code
After adding the plugin, go back to nav_Graph, switch to Design mode, and add parameters to the target page that you want to receive. Here, you need to pass parameters when FragmentA jumps to FragmentB, so set parameters for FragmentB, click FragmentB, Click + on the right of Arguments to enter the key value of the parameter and specify the parameter type and default value to quickly add parameters
After adding, rebuild the project, safeArgs will automatically generate some code, in the/build/generated/source/navigation – args directory can be seen
SafeArgs generates classes based on the fragment tag in the Nav_graph. The action tag is named “class name +Directions” and the argument tag is named “class name +Args”.
With safeArgs, the passing parameter looks like this
override fun onViewCreated(view: View, savedInstanceState: Bundle?). {
super.onViewCreated(view, savedInstanceState)
tv.setOnClickListener {
val navController = Navigation.findNavController(it)
// Pass parameters through safeArgs
val navDestination = FragmentADirections.actionFragmentAToFragmentB2("test")
navController.navigate(navDestination)
// Pass parameters in normal mode
// val bundle = Bundle()
// bundle.putString("key", "test")
// navController.navigate(R.id.action_fragmentA_to_fragmentB2, bundle)}}Copy the code
The receive parameters look like this
override fun onViewCreated(view: View, savedInstanceState: Bundle?). {
super.onViewCreated(view, savedInstanceState) arguments? .let {valvalue = FragmentBArgs.fromBundle(it).key ....... }... }Copy the code
Stack management
Click Destination and you’ll also see popUpTo, popUpToInclusive, and launchSingleTop in the right pane
- LaunchSingleTop: If the stack already contains the interface that you want to jump to, only one interface will be retained. If you do not specify the interface, the stack will display the same Fragment data for both interfaces. For example, FragmentA@1 -> FragmentA@2 and FragmentA@1 are destroyed, but FragmentA@01>FragmentB@02> 30000 is not destroyed.
- PopUpTo (tag) : jumps to a tag and pushes the elements above the tag off the stack.
- PopUpToInclusive: True means that tags will pop up, false does not
Example: FragmentA -> FragmentB -> FragmentC -> FragmentA
Set the action of FragmentC -> FragmentA to popUpTo=FragmentA, popUpToInclusive=false, then the stack element changes to
You’ll find that you need to press the back key twice to go back to the desktop
When popUpToInclusive=true, the stack element changes to
You only need to press the back key once to go back to the desktop, and you can see what popUpTo and popUpToInclusive mean.
deeplink
Deep links, that is, can directly jump to a page. Navigation creates deep links in both explicit and implicit ways
Create a new target page, FragmentDeepLink, that you want to open with a deep link,
Next, create a Deeplink for it
Nav_graph.xml generates the following code accordingly
<fragment
android:id="@+id/fragmentDeepLink"
android:name="com.example.testnavigation.FragmentDeepLink"
android:label="fragment_deep_link"
tools:layout="@layout/fragment_deep_link">
<argument
android:name="key"
android:defaultValue="Test"
app:argType="string" />
<deepLink
android:id="@+id/deepLink"
app:uri="www.deeplink.com/{id}" />
</fragment>
Copy the code
-
Show deep links
Use PendingIntent to navigate to a specific page, such as clicking a notification bar to quickly open the target page.
tv_deeplink.setOnClickListener { // Display deep links val notificationManager = NotificationManagerCompat.from(requireContext()) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val importance = NotificationManager.IMPORTANCE_DEFAULT val channel = NotificationChannel(channelId, channelName, importance) channel.description = "deeplink" notificationManager.createNotificationChannel(channel) } val navController = Navigation.findNavController(it) val deepLinkBuilder = navController.createDeepLink() val bundle = Bundle() bundle.putString("key"."deeplink") val pendingIntent = deepLinkBuilder // Pass in the graph resource file .setGraph(R.navigation.nav_graph) // Pass in parameters .setArguments(bundle) // Pass in the target page to be opened with a deep link .setDestination(R.id.fragmentDeepLink) .createPendingIntent() val builder = NotificationCompat.Builder(requireContext(), channelId) .setSmallIcon(R.drawable.ic_launcher_foreground) .setContentTitle("Test deepLink") .setContentText("Ha ha ha.") .setContentIntent(pendingIntent) .setAutoCancel(true) .setPriority(NotificationCompat.PRIORITY_DEFAULT) notificationManager.notify(1, builder.build()) } Copy the code
-
Implicit deep linking
Implicit links, which jump to a page via a URI when the user clicks on a link, have just been added for FragmentDeepLink in nav_graph.xml
<deepLink app:uri="www.deeplink.com/{id}" /> Copy the code
The URI does not declare whether it is HTTP or HTTPS, so both will match. Inside the braces are the parameters passed.
Androidmanifest.xml adds a
property to the activity to which the FragmentDeepLink belongs, which is MainActivity
<activity android:name=".MainActivity">.<nav-graph android:value="@navigation/nav_graph"/> </activity> Copy the code
App – > build – > outputs – > apk – > debug – > app-debug.apk
<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="http" />
<data
android:scheme="https" />
<data
android:host="www.deeplink.com" />
<data
android:pathPrefix="/" />
</intent-filter>
Copy the code
The Navigation component replaces the
You can test the effect of implicit deep linking with ADB by opening the command line for input
adb shell am start -a android.intent.action.VIEW -d "http://www.deeplink.com/1"
Copy the code
In the system pop-up window, select your own application to open, you can jump to the target page.
conclusion
This is the introduction of navigation, mainly introduced the basic use of navigation, the next part will be from the source Angle, navigation is how to do the page jump.
conclusion
Students who have problems or need to communicate with each other in the process can scan the QR code and add friends, and then enter the group to communicate with each other about problems and technologies.