Android Navigation Component แบบเบื้องต้น (Part 1)
เชื่อว่านักพัฒนา Android หลาย ๆ ท่านคงเคยผ่านการทำ Fragment Transaction มากันอยู่แล้ว แต่ชีวิตเราคงไม่เจอแค่การแสดง Fragment อันเดียวใน Activity แน่นอน หากแต่เรายังต้องเจอกับ Bottom Navigation Bar หรือ Navigation Drawer ที่จะทำให้การจัดการกับ Fragment Transaction ซับซ้อนมากขึ้น บทความนี้เลยจะพาคุณผู้อ่านไปพบกับ Navigation Component
Hello, Navigation Component
Navigation Component เป็น Library ตัวหนึ่งใน Android Jetpack ที่ Google ทำออกมาช่วยนักพัฒนาอย่างเรา ๆ มีคุณภาพชีวิตที่ดีขึ้น โดย Component ตัวนี้เรียกได้ว่าเป็น ตัวช่วยจัดการ Fragment เลยก็ว่าได้ เพราะคุณสมบัติหลัก ๆ ของมันคือช่วยเราในการทำ
- Fragment Transaction
- Handle Back Stack
- Passing Arguments
- Transition Animation
- Deeplinking
ใน Android Studio 3.3 ขึ้นไปเราจะได้พบกับ Navigation Editor ที่ช่วยให้เราเห็นภาพในการ Navigate Fragment และใช้ Feature ต่าง ๆ ของ Navigation Component ได้สะดวกขึ้น
Let’s Start
เราอยู่ในยุคสมัยของ Kotlin และ AndroidX แล้วเนอะ เพราะฉะนั้นในบทความนี้ผมจะใช้ Kotlin เป็นหลักนะครับ
เอาล่ะ เริ่มจากเพิ่ม dependency ของ Navigation Component ครับ
implementation "androidx.navigation:navigation-fragment-ktx:2.1.0"
implementation "androidx.navigation:navigation-ui-ktx:2.1.0"
และสิ่งที่เราจะต้องเพิ่มต่อไปก็คือ Navigation Graph
Navigation Graph
Navigation Graph คือ XML resource file ที่จะมีข้อมูลของการเชื่อมต่อกันระหว่าง NavHost และ Destination เช่ือมต่อกันด้วยสิ่งที่เรียกว่า Action โดยมี Navigation Controller เป็นตัวจัดการ navigate แต่ก่อนที่เราจะสร้างสี่สิ่งนี้ได้เราต้องสร้าง Navigation Graph resource file ซะก่อน
โดยคลิกขวาที่ res > Android Resource File > เลือก Resource type เป็น Navigation
ต่อไปเราจะมารู้จักส่วนสำคัญของ Navigation Component โดยมี 4 ส่วนดังนี้ครับ
- NavHost
- Destination
- Action
- Navigation Controller
NavHost
มี Fragment ที่ใด ที่นั่นย่อมมี Activity ที่นั่น หากให้พูดง่าย ๆ NavHost ก็คือ Activity ที่เราจะใส่ Fragment ลงไป
แต่เราต้องใส่ <fragment />
ไว้ใน XML Layout ของ Activity เพื่อทำให้ Activity ตัวนั้นกลายเป็น NavHost ก่อนนะ
app:navGraph ใส่ id ของ Navigation Graph เพื่อกำหนดว่า NavHost ตัวนั้นจะผูกกับ Navigation Graph ตัวไหน (สามารถดู id ได้ที่ resource file ของ Navigation Graph ตามรูปด้านล่างครับ)
app:defaultNavHost ใส่ค่า boolean เป็น true เพื่อกำหนดให้ NavHost นั้นจัดการกับปุ่ม back ให้เรา เช่นถ้าใน Activity เรามีการเปลี่ยน Fragment แล้วต้องการให้กด back เพื่อให้จัดการเรื่อง Fragment backstack ให้เราเลย ก็ set เป็น true เอาไว้ แต่ถ้า set เป็น false ก็จะเป็นการ back โดยไม่สนใจ back stack ของ fragment ครับ
Destination
คือ Activity หรือ Fragment ที่เราจะเชื่อมไปนั่นเอง หากเราเคยสร้างเอาไว้แล้ว เพียงกด New Destination ที่เป็นไอคอนเครื่องหมายบวกสีเขียว เราก็จะเห็นหน้าต่างแสดง Activity หรือ Fragment ที่เราได้สร้างไว้
แต่ถ้ายังไม่ได้สร้างไว้ก็เลือก Create New Destination เพื่อสร้างจากตรงนี้เลยก็ได้
พอเราคลิกเลือก Destination ที่ต้องการ มันก็จะมาปรากฏบน editor ให้เราดูแบบนี้
ถึงตรงนี้คุณผู้อ่านอาจจะสงสัยว่า
แล้ว Destination ไหนคือหน้าแรกที่จะแสดงล่ะ
ตรง Destination ที่ชื่อว่า firstFragment จะเห็นไอคอนรูป ‘ บ้าน ’ อยู่
นั่นคือสิ่งที่บ่งบอกถึง Start Destination หรือหน้าแรกที่จะแสดงนั่นแหละ ถ้าอยากเปลี่ยนหน้าแรกเพียงแค่เลือกที่ Destination น้ัน แล้วกดปุ่ม Assign start destination ด้านบน
หรือจะไปกำหนดเองใน XML ของ navigation graph ก็ได้นะ
ต่อไปจะเป็นขั้นตอนของการเปลี่ยนหน้าแล้วครับ การจะ navigate ไปยังหน้าอื่นนั้นเราจะใช้สิ่งที่เรียกว่า…
Action
ใน editor เราสามารถสร้าง Action ได้ง่าย ๆ เพียงการลากเส้นจาก Destination นึงไปอีก Destination นึง
จากนั้น Android Studio จะ generate code สำหรับ <action />
ให้เรา
android:id คือ id ของ action ซึ่งเราจะนำไปใช้ตอนที่เราสั่งให้ Activity หรือ Fragment ขอเราทำการ navigate
app:destination คือ destination ที่ action นี้จะ navigate ไป
และแน่นอนว่าเราจะต้องไปสั่งเปลี่ยนหน้าใน Activity หรือ Fragment ด้วย โดยเราจะต้องเรียก Navigation Controller ออกมาก่อนจึงจะ Navigate ได้
Navigation Controller
การที่เราจะเปลี่ยน Destination ใน NavHost หรือการเปลี่ยน Fragment ใน Activity นั่นแหละ เราจะต้องเรียก Navigation Controller แล้วสั่งให้มันเปลี่ยน Destination ให้เรา ในแต่ละ NavHost ก็จะมี Controller เป็นของตัวเองนะ ส่วนวิธีเรียกก็มีดังนี้
Fragment.findNavController()
View.findNavController()
Activity.findNavController(viewId: Int)
นอกจากนี้เราสามารถกำหนด Animation ให้กับ Action ได้ด้วยนะ
Enter: Animation ของ Destination ต่อไปที่จะเข้ามา
Exit: Animation ของ Destination ปัจจุบันที่กำลังจะโดนเปลี่ยน
Pop Enter: Animation ของ Destination ก่อนหน้าที่จะเข้ามา เมื่อกด Back
Pop Exit: Animation ของ Destination ปัจจุบันที่จะโดนเปลี่ยน เมื่อกด Back
Navigation Component จะมี Animation พื้นฐานมาให้เราอยู่แล้วน่ะ แต่หากคุณผู้อ่านต้องการทำ Custom animation เองเพียงแค่สร้างเอาไว้ใน Anim resource แล้วเลือก Animation เหล่านั้นใน editor ได้เลย
สรุป
Navigation Component ช่วยเราได้มากในการจัดการกับการกับ Fragment Transaction มันจึงเหมาะมาก ๆ กับพวก Bottom Navigation Bar หรือ Navigation Drawer และโดยเฉพาะการทำ Single Activity มันช่วยเราจัดการทั้ง backstack, animation, passing data แถมมี editor ให้เราเห็นภาพ flow ของแอปอีก ทำไมจะไม่น่าใช้ล่ะ!
ทั้งหมดในเบื้องต้นก็มีเท่านี้ครับ Part ต่อไปจะเป็นเรื่องการส่งค่าไปยัง Destination ด้วย Safe Args ครับ
และนี่ก็เป็นตัวอย่าง Code สำหรับ Part นี้ครับ