นำทางไปยังจุดหมาย

คอมโพเนนต์การนำทางมีวิธีที่ตรงไปตรงมาและทั่วไปในการ ไปยังปลายทาง อินเทอร์เฟซนี้รองรับบริบทและเฟรมเวิร์ก UI ที่หลากหลาย เช่น คุณสามารถใช้คอมโพเนนต์การนำทางกับ Compose, View, Fragment, Activity และแม้แต่เฟรมเวิร์ก UI ที่กำหนดเองได้

คู่มือนี้อธิบายวิธีใช้คอมโพเนนต์การนำทางเพื่อไปยังปลายทางในบริบทต่างๆ

ใช้ NavController

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

ไม่ว่าคุณจะใช้เฟรมเวิร์ก UI ใด ก็มีฟังก์ชันเดียวที่คุณใช้เพื่อไปยังปลายทางได้ คือ NavController.navigate()

มีโอเวอร์โหลดมากมายสำหรับ navigate() การโอเวอร์โหลดที่คุณควรเลือกจะสอดคล้องกับบริบทที่แน่นอนของคุณ เช่น คุณควรใช้การโอเวอร์โหลดหนึ่งเมื่อไปยัง Composable และอีกหนึ่งเมื่อไปยัง View

ส่วนต่อไปนี้จะอธิบายการโอเวอร์โหลด navigate() ที่สำคัญบางส่วนที่คุณใช้ได้

ไปยัง Composable

หากต้องการไปยัง Composable คุณควรใช้ NavController.navigate<T> เมื่อมีการโอเวอร์โหลดนี้ navigate() จะใช้อาร์กิวเมนต์ route เดียวที่คุณส่งประเภท ซึ่งเป็นกุญแจสำคัญในการเดินทางไปยังจุดหมาย

@Serializable
object FriendsList

navController.navigate(route = FriendsList)

หากต้องการไปยัง Composable ในกราฟการนำทาง ให้กำหนด NavGraph ก่อนเพื่อให้แต่ละปลายทางสอดคล้องกับประเภท สำหรับ Composable คุณทำได้โดยใช้ฟังก์ชัน composable()

เปิดเผยเหตุการณ์จาก Composable

เมื่อฟังก์ชันที่ประกอบกันได้ต้องไปยังหน้าจอใหม่ คุณไม่ควรส่ง การอ้างอิงไปยัง NavController เพื่อให้เรียก navigate() ได้โดยตรง ตามหลักการโฟลว์ข้อมูลแบบทิศทางเดียว (UDF) คอมโพสได้ ควรแสดงเหตุการณ์ที่ NavController จัดการแทน

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

ดูตัวอย่างได้ในส่วนย่อยต่อไปนี้

ตัวอย่าง

เพื่อเป็นการสาธิตส่วนก่อนหน้า ให้สังเกตจุดต่อไปนี้ใน ข้อมูลโค้ดต่อไปนี้

  1. ปลายทางแต่ละแห่งในกราฟสร้างขึ้นโดยใช้เส้นทาง ซึ่งเป็นออบเจ็กต์หรือคลาสที่สามารถแปลงเป็นอนุกรมได้ซึ่งอธิบายข้อมูลที่ปลายทางนั้นๆ ต้องการ
  2. ฟังก์ชันที่ประกอบกันได้ MyAppNavHost จะมีอินสแตนซ์ NavController
  3. ดังนั้น การเรียกใช้ navigate() ควรเกิดขึ้นที่นั่นและไม่ควรเกิดขึ้นใน Composable ระดับล่าง เช่น ProfileScreen
  4. ProfileScreen มีปุ่มที่นำผู้ใช้ไปยัง FriendsList เมื่อคลิก แต่จะไม่เรียกใช้ navigate() ด้วยตัวเอง
  5. แต่ปุ่มจะเรียกฟังก์ชันที่แสดงเป็นพารามิเตอร์ onNavigateToFriends
  6. เมื่อ MyAppNavHost เพิ่ม ProfileScreen ลงในกราฟการนำทาง สำหรับ onNavigateToFriends จะส่ง Lambda ที่เรียก navigate(route = FriendsList)
  7. ซึ่งช่วยให้มั่นใจได้ว่าเมื่อผู้ใช้กดปุ่ม ProfileScreen ผู้ใช้จะ ไปยัง FriendsListScreen ได้อย่างถูกต้อง
@Serializable
object Profile
@Serializable
object FriendsList

@Composable
fun MyAppNavHost(
    modifier: Modifier = Modifier,
    navController: NavHostController = rememberNavController(),
) {
    NavHost(
        modifier = modifier,
        navController = navController,
        startDestination = Profile
    ) {
        composable<Profile> {
            ProfileScreen(
                onNavigateToFriends = { navController.navigate(route = FriendsList) },
                /*...*/
            )
        }
        composable<FriendsList> { FriendsListScreen(/*...*/) }
    }
}

@Composable
fun ProfileScreen(
    onNavigateToFriends: () -> Unit,
    /*...*/
) {
    /*...*/
    Button(onClick = onNavigateToFriends) {
        Text(text = "See friends list")
    }
}

ไปยังส่วนต่างๆ โดยใช้รหัสจำนวนเต็ม

หากต้องการไปยังปลายทางโดยใช้รหัสจำนวนเต็ม ให้เรียกใช้navigate(int) โอเวอร์โหลด โดยจะใช้รหัสทรัพยากรของทั้งการกระทําหรือปลายทาง ข้อมูลโค้ดต่อไปนี้แสดงวิธีใช้การโอเวอร์โหลดนี้เพื่อไปยังViewTransactionsFragment

Kotlin

viewTransactionsButton.setOnClickListener { view ->
  view.findNavController().navigate(R.id.viewTransactionsAction)
}

Java

viewTransactionsButton.setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View view) {
      Navigation.findNavController(view).navigate(R.id.viewTransactionsAction);
  }
});

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

ไปยังส่วนต่างๆ จาก Compose ในแอปที่ใช้ Fragment

หากใช้ Jetpack Compose ภายในสถาปัตยกรรมการนำทางที่อิงตาม Fragment (เช่น ในแอปที่ใช้ทั้ง View และ Compose) คุณจะใช้เส้นทาง Compose ที่ปลอดภัยตามประเภทเพื่อไปยังส่วนต่างๆ โดยตรงไม่ได้ แต่คุณต้องใช้รหัสจำนวนเต็ม (การดำเนินการ) ที่กำหนดไว้ในกราฟการนำทาง XML

หากต้องการเปลี่ยนปลายทางจากโค้ด Compose ให้แสดงเหตุการณ์ (Lambda) จาก Composable ดังนี้

@Composable
fun MyScreen(onNavigateToProfile: () -> Unit) {
    Button(onClick = { onNavigateToProfile() }) {
        Text("Go to Profile")
    }
}

ใน Fragment ให้เชื่อมต่อ Compose กับคอมโพเนนต์การนำทางที่อิงตาม Fragment โดยเรียกใช้ NavController ของ Fragment เมื่อมีการทริกเกอร์เหตุการณ์

override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
): View {
    return ComposeView(requireContext()).apply {
        setContent {
            MyScreen(onNavigateToProfile = { findNavController().navigate(R.id.nav_profile) })
        }
    }
}

แนวทางนี้ช่วยให้ Composable สามารถนำกลับมาใช้ซ้ำและทดสอบได้ เนื่องจากไม่ได้ ขึ้นอยู่กับ NavController ของ Fragment โดยตรง

ไปยังส่วนต่างๆ โดยใช้ NavDeepLinkRequest

หากต้องการไปยังปลายทางของ Implicit Deep Link ให้ใช้การโอเวอร์โหลด navigate(NavDeepLinkRequest) ข้อมูลโค้ดต่อไปนี้แสดงการติดตั้งใช้งานเมธอดนี้

Kotlin

val request = NavDeepLinkRequest.Builder
  .fromUri("android-app://androidx.navigation.app/profile".toUri())
  .build()
findNavController().navigate(request)

Java

NavDeepLinkRequest request = NavDeepLinkRequest.Builder
  .fromUri(Uri.parse("android-app://androidx.navigation.app/profile"))
  .build()
NavHostFragment.findNavController(this).navigate(request)

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

การดำเนินการและประเภท MIME

นอกจาก Uri แล้ว NavDeepLinkRequest ยังรองรับ Deep Link ที่มี การดำเนินการและประเภท MIME ด้วย หากต้องการเพิ่มการดำเนินการในคำขอ ให้ใช้ fromAction() หรือ setAction() หากต้องการเพิ่มประเภท MIME ลงในคำขอ ให้ใช้ fromMimeType() หรือ setMimeType()

หากต้องการให้ NavDeepLinkRequest ตรงกับปลายทางของ Implicit Deep Link โดยนัยอย่างถูกต้อง URI, การดำเนินการ และประเภท MIME ต้องตรงกับ NavDeepLink ใน ปลายทาง URI ต้องตรงกับรูปแบบ การดำเนินการต้องตรงกันทุกประการ และประเภท MIME ต้องเกี่ยวข้อง เช่น image/jpg จะตรงกับ image/\*

บริบทเพิ่มเติม

เอกสารนี้ครอบคลุมวิธีใช้ NavController.navigate() ในกรณีการใช้งานที่พบบ่อยที่สุด อย่างไรก็ตาม ฟังก์ชันนี้มีการโอเวอร์โหลดหลายอย่างที่คุณใช้ได้ในบริบทต่างๆ และใช้ร่วมกับเฟรมเวิร์ก UI ใดก็ได้ ดูรายละเอียดเพิ่มเติมเกี่ยวกับการโอเวอร์โหลดเหล่านี้ในเอกสารประกอบอ้างอิง

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

ดูข้อมูลเพิ่มเติมได้ที่หน้าต่อไปนี้