ออกแบบกราฟการนำทาง

คอมโพเนนต์การนำทางใช้กราฟการนำทางเพื่อจัดการ การนำทาง กราฟการนำทางคือโครงสร้างข้อมูลที่มี ปลายทางภายในแอปของคุณ และการเชื่อมต่อ ระหว่างปลายทางเหล่านั้น

ประเภทปลายทาง

ปลายทางทั่วไปมี 3 ประเภท ได้แก่ โฮสต์ กล่องโต้ตอบ และกิจกรรม ตารางต่อไปนี้จะสรุปประเภทปลายทาง 3 ประเภทและวัตถุประสงค์

ประเภท

คำอธิบาย

กรณีการใช้งาน

โฮสต์

แสดงโฮสต์การนำทางทั้งหมด กล่าวคือ ปลายทางที่โฮสต์จะมีขนาดเท่ากับขนาดของโฮสต์การนำทางและปลายทางก่อนหน้าจะไม่ปรากฏ

หน้าจอหลักและหน้าจอรายละเอียด

Dialog

แสดงคอมโพเนนต์ UI แบบวางซ้อน UI นี้ไม่ได้เชื่อมโยงกับตำแหน่งของโฮสต์การนำทางหรือขนาดของโฮสต์ โดยจุดหมายก่อนหน้าจะแสดงอยู่ใต้จุดหมายนั้น

การแจ้งเตือน การเลือก แบบฟอร์ม

กิจกรรม

แสดงหน้าจอหรือฟีเจอร์ที่ไม่ซ้ำภายในแอป

ทำหน้าที่เป็นจุดออกไปยังกราฟการนำทางที่เริ่มกิจกรรม Android ใหม่ที่มีการจัดการแยกจากคอมโพเนนต์การนำทาง

ในการพัฒนา Android สมัยใหม่ แอปประกอบด้วยกิจกรรมเดียว ดังนั้นจึงควรใช้ปลายทางกิจกรรมเมื่อโต้ตอบกับกิจกรรมของบุคคลที่สามหรือเป็นส่วนหนึ่งของกระบวนการย้ายข้อมูล

เอกสารนี้มีตัวอย่างของปลายทางที่โฮสต์ ปลายทางพื้นฐานและปลายทางทั่วไป ดูคำแนะนำต่อไปนี้ สำหรับข้อมูลเกี่ยวกับ จุดหมายอื่นๆ ได้แก่

กรอบการทำงาน

แม้ว่าเวิร์กโฟลว์ทั่วไปจะเหมือนกันในทุกกรณี แต่วิธีสร้าง โฮสต์และกราฟการนำทางขึ้นอยู่กับเฟรมเวิร์ก UI ที่คุณใช้

  • Compose: ใช้ NavHost Composable เพิ่ม NavGraph ลงในรายการโดยใช้ Kotlin DSL คุณสามารถสร้างกราฟได้ 2 วิธีดังนี้
    • เป็นส่วนหนึ่งของ NavHost: สร้างกราฟการนำทางโดยตรงตาม ส่วนหนึ่งของการเพิ่ม NavHost
    • แบบเป็นโปรแกรม: ใช้เมธอด NavController.createGraph() เพื่อสร้าง NavGraph และส่งไปยัง NavHost โดยตรง
  • ส่วนย่อย: เมื่อใช้ส่วนย่อยกับเฟรมเวิร์ก UI ของมุมมอง ให้ใช้ NavHostFragment ในฐานะผู้จัด การสร้างการนำทางทำได้หลายวิธี กราฟ:
    • แบบเป็นโปรแกรม: ใช้ Kotlin DSL เพื่อสร้าง NavGraph และ ใช้กับ NavHostFragment โดยตรง
      • ฟังก์ชัน createGraph() ที่ใช้กับ Kotlin DSL สำหรับทั้ง 2 กลุ่ม ส่วนย่อยและ Compose เหมือนกัน
    • XML: เขียนโฮสต์การนำทางและกราฟโดยตรงใน XML
    • ตัวแก้ไข Android Studio: ใช้เครื่องมือแก้ไข GUI ใน Android Studio เพื่อ สร้างและปรับกราฟของคุณเป็นไฟล์ทรัพยากร XML

เขียน

ใน Compose ให้ใช้ออบเจ็กต์หรือคลาสที่ทำให้อนุกรมได้เพื่อกำหนดเส้นทาง เส้นทาง A อธิบายวิธีไปยังปลายทาง และมีข้อมูลทั้งหมดที่ ปลายทางที่ต้องการ เมื่อคุณกำหนดเส้นทางแล้ว ให้ใช้ NavHost Composable เพื่อสร้างกราฟการนำทาง ลองดูตัวอย่างต่อไปนี้

@Serializable
object Profile
@Serializable
object FriendsList

val navController = rememberNavController()

NavHost(navController = navController, startDestination = Profile) {
    composable<Profile> { ProfileScreen( /* ... */ ) }
    composable<FriendsList> { FriendsListScreen( /* ... */ ) }
    // Add more destinations similarly.
}
  1. ออบเจ็กต์ที่เรียงลำดับได้จะแสดงเส้นทาง 2 เส้นทาง ได้แก่ Profile และ FriendsList
  2. การเรียกไปยัง NavHost Composable ผ่าน NavController และเส้นทาง ของปลายทางเริ่มต้น
  3. แลมบ์ดาผ่านการโทรไปให้ NavHost NavController.createGraph() และส่งคืน NavGraph
  4. แต่ละเส้นทางถูกกำหนดเป็นอาร์กิวเมนต์ประเภทสำหรับ NavGraphBuilder.composable<T>() ซึ่งเพิ่มปลายทางไปยัง ผลลัพธ์เป็น NavGraph
  5. lambda ที่ส่งไปยัง composable คือสิ่งที่ NavHost แสดงในกรณีนี้ ปลายทาง

ทำความเข้าใจค่าแลมบ์ดา

หากต้องการทำความเข้าใจ lambda ที่สร้าง NavGraph ให้ดียิ่งขึ้น ให้พิจารณาถึง สร้างกราฟเดียวกับในข้อมูลโค้ดก่อนหน้านี้ คุณสามารถสร้าง NavGraph แยกต่างหากโดยใช้ NavController.createGraph() และส่งไปยัง NavHost โดยตรง:

val navGraph by remember(navController) {
  navController.createGraph(startDestination = Profile)) {
    composable<Profile> { ProfileScreen( /* ... */ ) }
    composable<FriendsList> { FriendsListScreen( /* ... */ ) }
  }
}
NavHost(navController, navGraph)

ผ่านอาร์กิวเมนต์

หากจำเป็นต้องส่งข้อมูลไปยังปลายทาง ให้กำหนดเส้นทางกับคลาสที่ มีพารามิเตอร์ เช่น เส้นทาง Profile คือคลาสข้อมูลที่มี name พารามิเตอร์

@Serializable
data class Profile(val name: String)

เมื่อใดก็ตามที่คุณต้องการส่งอาร์กิวเมนต์ไปยังปลายทางนั้น ให้คุณสร้างอินสแตนซ์ ของคลาสเส้นทางของคุณ โดยส่งต่ออาร์กิวเมนต์ไปยังตัวสร้างคลาส

สําหรับอาร์กิวเมนต์ที่ไม่บังคับ ให้สร้างช่องที่เป็นค่าว่างด้วยค่าเริ่มต้น

@Serializable
data class Profile(val nickname: String? = null)

รับอินสแตนซ์เส้นทาง

คุณสามารถรับข้อมูลอินสแตนซ์ของเส้นทางได้ด้วย NavBackStackEntry.toRoute() หรือ SavedStateHandle.toRoute() เมื่อคุณสร้างปลายทางโดยใช้ composable() คุณสามารถใช้ NavBackStackEntry เป็นพารามิเตอร์ได้

@Serializable
data class Profile(val name: String)

val navController = rememberNavController()

NavHost(navController = navController, startDestination = Profile(name="John Smith")) {
    composable<Profile> { backStackEntry ->
        val profile: Profile = backStackEntry.toRoute()
        ProfileScreen(name = profile.name) }
}

สิ่งที่ควรทราบในข้อมูลโค้ดนี้

  • เส้นทาง Profile ระบุจุดหมายเริ่มต้นในการนำทาง กราฟ โดยมี "John Smith" เป็นอาร์กิวเมนต์สำหรับ name
  • ส่วนปลายทางเองคือบล็อก composable<Profile>{}
  • Composable ProfileScreen จะใช้ค่า profile.name ของตัวเอง อาร์กิวเมนต์ name
  • ด้วยเหตุนี้ ค่า "John Smith" จะส่งต่อไปยัง ProfileScreen

ตัวอย่างขั้นต่ำ

ตัวอย่างที่สมบูรณ์ของ NavController และ NavHost ที่ทำงานร่วมกัน

@Serializable
data class Profile(val name: String)

@Serializable
object FriendsList

// Define the ProfileScreen composable.
@Composable
fun ProfileScreen(
    profile: Profile
    onNavigateToFriendsList: () -> Unit,
  ) {
  Text("Profile for ${profile.name}")
  Button(onClick = { onNavigateToFriendsList() }) {
    Text("Go to Friends List")
  }
}

// Define the FriendsListScreen composable.
@Composable
fun FriendsListScreen(onNavigateToProfile: () -> Unit) {
  Text("Friends List")
  Button(onClick = { onNavigateToProfile() }) {
    Text("Go to Profile")
  }
}

// Define the MyApp composable, including the `NavController` and `NavHost`.
@Composable
fun MyApp() {
  val navController = rememberNavController()
  NavHost(navController, startDestination = Profile(name = "John Smith")) {
    composable<Profile> { backStackEntry ->
        val profile: Profile = backStackEntry.toRoute()
        ProfileScreen(
            profile = profile,
            onNavigateToFriendsList = {
                navController.navigate(route = FriendsList)
            }
        )
    }
    composable<FriendsList> {
      FriendsListScreen(
        onNavigateToProfile = {
          navController.navigate(
            route = Profile(name = "Aisha Devi")
          )
        }
      )
    }
  }
}

ตามที่แสดงตัวอย่าง แทนที่จะส่ง NavController ไปยัง Composable จะแสดงเหตุการณ์ใน NavHost กล่าวคือ Composable ควร มีพารามิเตอร์ประเภท () -> Unit ซึ่ง NavHost ส่ง lambda ที่โทรหา NavController.navigate()

ส่วนย่อย

ตามที่อธิบายไว้ในส่วนก่อนหน้านี้ เมื่อใช้ Fragment คุณจะมีตัวเลือก เพื่อสร้างกราฟการนำทางแบบเป็นโปรแกรมโดยใช้ Kotlin DSL, XML หรือ ตัวแก้ไขของ Android Studio

ส่วนต่อไปนี้จะแสดงรายละเอียดวิธีการต่างๆ

แบบเป็นโปรแกรม

Kotlin DSL มีวิธีแบบเป็นโปรแกรมสำหรับการสร้างกราฟการนำทางด้วย ส่วนย่อย ในหลายๆ ด้าน วิธีนี้ดูเรียบร้อยกว่าและทันสมัยกว่าการใช้ XML ไฟล์ทรัพยากร

ลองดูตัวอย่างต่อไปนี้ ซึ่งจะแสดงกราฟการนำทางแบบ 2 หน้าจอ

ก่อนอื่น คุณต้องสร้าง NavHostFragment ซึ่งต้องไม่มี องค์ประกอบ app:navGraph:

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

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</FrameLayout>

ถัดไป ส่ง id จาก NavHostFragment ไปยัง NavController.findNavController การดำเนินการนี้จะเชื่อมโยง NavController กับ NavHostFragment

ผลที่ตามมาคือ การเรียก NavController.createGraph() จึงเชื่อมโยงกราฟกับ NavController และส่งผลต่อ NavHostFragment ด้วย:

@Serializable
data class Profile(val name: String)

@Serializable
object FriendsList

// Retrieve the NavController.
val navController = findNavController(R.id.nav_host_fragment)

// Add the graph to the NavController with `createGraph()`.
navController.graph = navController.createGraph(
    startDestination = Profile(name = "John Smith")
) {
    // Associate each destination with one of the route constants.
    fragment<ProfileFragment, Profile> {
        label = "Profile"
    }

    fragment<FriendsListFragment, FriendsList>() {
        label = "Friends List"
    }

    // Add other fragment destinations similarly.
}

การใช้ DSL ในลักษณะนี้คล้ายกับเวิร์กโฟลว์ที่ระบุไว้ใน ส่วนก่อนหน้าในเขียน ตัวอย่างเช่น ทั้งตรงนี้และที่นี่ ฟังก์ชัน NavController.createGraph() จะสร้าง NavGraph และในทำนองเดียวกัน NavGraphBuilder.composable() เพิ่มปลายทางที่ประกอบกันได้ลงในกราฟ ที่นี่ NavGraphBuilder.fragment() เพิ่มปลายทางของส่วนย่อย

ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีใช้ Kotlin DSL ได้ที่สร้างกราฟด้วย NavGraphBuilder DSL

XML

คุณสามารถเขียน XML ด้วยตัวเองได้โดยตรง ตัวอย่างต่อไปนี้สะท้อนให้เห็นและ เทียบเท่ากับตัวอย่าง 2 หน้าจอจากส่วนก่อนหน้านี้

ก่อนอื่นให้สร้าง NavHostFragment ทำหน้าที่เป็นโฮสต์การนำทางซึ่ง ที่มีกราฟการนำทางจริง

การใช้ NavHostFragment ให้น้อยที่สุด:

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

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:navGraph="@navigation/nav_graph" />

</FrameLayout>

NavHostFragment มีแอตทริบิวต์ app:navGraph ใช้แอตทริบิวต์นี้ เพื่อเชื่อมต่อกราฟการนำทางกับโฮสต์การนำทาง ต่อไปนี้เป็น ตัวอย่างวิธีนำกราฟนี้ไปใช้:

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/nav_graph"
    app:startDestination="@id/profile">

    <fragment
        android:id="@+id/profile"
        android:name="com.example.ProfileFragment"
        android:label="Profile">

        <!-- Action to navigate from Profile to Friends List. -->
        <action
            android:id="@+id/action_profile_to_friendslist"
            app:destination="@id/friendslist" />
    </fragment>

    <fragment
        android:id="@+id/friendslist"
        android:name="com.example.FriendsListFragment"
        android:label="Friends List" />

    <!-- Add other fragment destinations similarly. -->
</navigation>

คุณใช้การทำงานเพื่อกำหนดการเชื่อมต่อระหว่างปลายทางต่างๆ ได้ ใน ตัวอย่างนี้ ส่วนย่อย profile มีการดำเนินการที่ไปยัง friendslist สำหรับข้อมูลเพิ่มเติม โปรดดูที่ใช้การทำงานการนำทางและ ส่วนย่อย

ผู้แก้ไข

คุณจัดการกราฟการนำทางของแอปได้โดยใช้เครื่องมือแก้ไขการนำทางใน Android Studio นี่คือ GUI ที่คุณสามารถใช้เพื่อสร้างและแก้ไข NavigationFragment XML ตามที่เห็นในส่วนก่อนหน้านี้

ดูข้อมูลเพิ่มเติมได้ที่ตัวแก้ไขการนำทาง

กราฟแบบฝัง

หรือคุณจะใช้กราฟแบบซ้อนก็ได้ ซึ่งต้องใช้กราฟเป็นการนำทาง ปลายทาง ดูข้อมูลเพิ่มเติมได้ที่กราฟที่ซ้อนกัน

อ่านเพิ่มเติม

ดูแนวคิดหลักอื่นๆ ในการไปยังส่วนต่างๆ ได้จากคำแนะนำต่อไปนี้

  • ภาพรวม: โปรดอ่านภาพรวมทั่วไปของการนำทาง คอมโพเนนต์
  • ปลายทางกิจกรรม: ตัวอย่างวิธีใช้ปลายทาง ที่พาผู้ใช้ไปยังกิจกรรมต่างๆ
  • ปลายทางของกล่องโต้ตอบ: ตัวอย่างวิธีสร้างปลายทางที่ เพื่อนำผู้ใช้ไปยังกล่องโต้ตอบ
  • ไปยังปลายทาง: คำแนะนำโดยละเอียดซึ่งครอบคลุมวิธีการ นำทางจากปลายทางหนึ่งไปยังอีกปลายทางหนึ่ง
  • กราฟที่ซ้อนกัน: คำแนะนำแบบเจาะลึกเกี่ยวกับวิธีซ้อนการนำทาง ภายในอีกอุปกรณ์หนึ่ง