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

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

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

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

ประเภท

คำอธิบาย

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

โฮสต์

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

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

Dialog

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

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

กิจกรรม

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

ใช้เป็นจุดสิ้นสุดของกราฟการนําทางที่เริ่มกิจกรรม Android ใหม่ซึ่งจัดการแยกจากคอมโพเนนต์การนําทาง

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

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

เฟรมเวิร์ก

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

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

เขียน

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

ใช้คำอธิบายประกอบ @Serializable เพื่อสร้างเมธอดการแปลงเป็นอนุกรมและถอดรหัสที่จำเป็นโดยอัตโนมัติสำหรับประเภทเส้นทาง คําอธิบายประกอบนี้มาจากปลั๊กอินการแปลงข้อมูล Kotlin ทําตามวิธีการเหล่านี้เพื่อเพิ่มปลั๊กอินนี้

เมื่อกําหนดเส้นทางแล้ว ให้ใช้คอมโพสิเบิล NavHost เพื่อสร้างกราฟการนําทาง ลองดูตัวอย่างต่อไปนี้

@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 จะส่ง NavController และเส้นทางสำหรับจุดหมายเริ่มต้น
  3. แลมดาที่ส่งไปยัง NavHost จะเรียกใช้ NavController.createGraph() ในท้ายที่สุดและแสดงผล NavGraph
  4. แต่ละเส้นทางจะส่งเป็นอาร์กิวเมนต์ประเภทไปยัง NavGraphBuilder.composable<T>() ซึ่งจะเพิ่มปลายทางไปยัง NavGraph ที่ได้
  5. Lambda ที่ส่งไปยัง composable คือสิ่งที่ NavHost แสดงสําหรับปลายทางนั้น

ทําความเข้าใจเกี่ยวกับ Lambda

หากต้องการทําความเข้าใจ 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)

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

สำหรับอาร์กิวเมนต์ที่ไม่บังคับ ให้สร้างฟิลด์ที่อนุญาตค่า Null ที่มีค่าเริ่มต้น

@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>{}
  • คอมโพสิเบิล 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 ไปยังคอมโพสิเบิล ให้แสดงเหตุการณ์ต่อ NavHost กล่าวคือ คอมโพสิเบิลควรมีพารามิเตอร์ประเภท () -> Unit ซึ่ง NavHost ส่งผ่าน Lambda ที่เรียก NavController.navigate()

ส่วนย่อย

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

ส่วนต่อไปนี้จะอธิบายแนวทางต่างๆ เหล่านี้โดยละเอียด

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

Kotlin DSL มีวิธีแบบเป็นโปรแกรมในการสร้างกราฟการนำทางด้วยฟragment วิธีนี้เรียบร้อยและทันสมัยกว่าการใช้ไฟล์ทรัพยากร 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 ได้ที่สร้างกราฟด้วย DSL ของ NavGraphBuilder

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 ได้ ดังที่แสดงในส่วนก่อนหน้า

ดูข้อมูลเพิ่มเติมได้ที่เครื่องมือแก้ไขการนําทาง

กราฟแบบฝัง

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

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

ดูแนวคิดการนําทางหลักเพิ่มเติมได้ในคู่มือต่อไปนี้

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