Android Navigation Component คืออะไรน้าา? — Part.1

Natcha Jintanasatien
te<h @TDG
Published in
4 min readApr 29, 2020

คืออะไรน้าา?

ก็คือ Component นั่นเอง ที่อยู่ในหมวด Architecture ของ Android Jetpack เปิดตัวขึ้นในงาน Google I/O 2018 ที่ผ่านมา

Navigation มีความโดดเด่นในเรื่องการจัดการ flow ของ app ในการ navigate ไปยัง screen ต่างๆ ซึ่งมีลักษณะคล้ายกับ Storyboard ใน XCode ของ iOS เลยค่ะ

ใช้ได้ที่ Android Studio 3.3 ขึ้นไป

CONCEPT = Single Activity More Fragment

แล้วดียังไงล่ะ?

  • เห็นภาพ flow ของ app ว่าแต่ละ screen มีการ navigate ไปไหนบ้าง
  • ช่วยจัดการ fragment transaction ให้เอง (back stack ordering)
  • ทำ animation และ transition ได้
  • Passing data โดย Safe Args
  • Deeplink

Navigation Component ประกอบไปด้วย

  1. Navigation Graph คือ XML resource file ทำหน้าที่เชื่อมต่อ NavHostFragment กับ Destination (Screen ต่างๆ) เข้าด้วยกัน รวมถึงการกำหนด action ให้กับ Destination
  2. NavHostFragment เป็น Container ที่เอาไว้แสดง Destination โดยใส่ไว้ใน Layout ของ Activity
  3. NavController ไว้จัดการเรื่อง navigate
Credit : Android Developers Channel

สำหรับบทความนี้จะพาไปทำ Navigation แบบเบื้องต้นกันค่ะ

โจทย์คือ

มี MainActivity ไว้วาง MainFragment และMainFragment มีปุ่มกดเพื่อเปิด AboutFragment ตามรูป

Flow Example App

Getting Started

เพิ่ม dependencies ใน build.gradle(app) ดังนี้

dependencies of navigation

จากนั้นสร้าง Navigation Graph โดยคลิกขวาที่โฟลเดอร์ res เลือก New > Android Resource File แล้วเลือก Resource type: Navigation และตั้งชื่อไฟล์

New Resource File: Navigation

จะได้ไฟล์ nav_graph_main.xml ในโฟลเดอร์ navigation ตามรูป

position of navigation graph

หน้าตาของ navigation graph เป็นดังนี้ ยังไม่มี screen ใดๆเลย

navigation graph

จากนั้น implement NavHost ที่ main_activity.xml ตามนี้

<?xml version="1.0" encoding="utf-8"?>
<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/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/nav_graph_main" />
</androidx.constraintlayout.widget.ConstraintLayout>
  • android:name=“androidx.navigation.fragment.NavHostFragment”
  • app:defaultNavHost ใส่ค่า boolean ถ้าใส่ true คือ กำหนดให้ NavHost นั้นจัดการกับปุ่ม back ให้เรา
  • app:navGraph ใส่ id ของ Navigation Graph (ไม่ใช่ชื่อไฟล์นะ อาจจะสับสนได้เพราะ id กับชื่อไฟล์เหมือนกัน)
id of Navigation Graph

ทำความรู้จัก Navigation Graph กันก่อนค่ะ

  1. Destinations แสดง Host ที่ Navigation Graph นี้เชื่อมต่ออยู่ และ destination ที่ใช้ทั้งหมด
  2. Editor
  3. Attributes
  4. ปุ่ม New Destination ไว้เพิ่ม destination ที่ต้องการ
New Destination

** Destination คือ activity หรือ fragment นั่นเอง **

<fragment
android:id="@+id/aboutFragment"
android:name="com.abc.workshop.AboutFragment"
android:label="About Fragment"
tools:layout="@layout/fragment_about" />

5. ปุ่ม Assign Start Destination ไว้กำหนดหน้าแรกให้กับ Navigation Graph สังเกตได้จากไอคอน Home หรือกำหนดที่ xml ได้เหมือนกัน

app:startDestination="@id/{idของFragment}"
Start Destination

6. เส้น Action ใน editor สามารถลากจาก destination หนึ่งไปยังอีก destination ได้เลย หรือกำหนดใน xml

ผลลัพธ์

Result
<?xml version="1.0" encoding="utf-8"?>
<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_main"
app:startDestination="@id/mainFragment">
<fragment
android:id="@+id/mainFragment"
android:name="com.truedigital.workshop.MainFragment"
android:label="Main Fragment"
tools:layout="@layout/fragment_main">
<action
android:id="@+id/action_mainFragment_to_aboutFragment"
app:destination="@id/aboutFragment" />

</fragment>
<fragment
android:id="@+id/aboutFragment"
android:name="com.truedigital.workshop.AboutFragment"
android:label="About Fragment"
tools:layout="@layout/fragment_about" />
</navigation>

แล้วจะเปิด AboutFragment ได้ยังไงล่ะ

  1. ใส่ <action …/> ใน navigation graph
<action
android:id="@+id/action_mainFragment_to_aboutFragment"
app:destination="@id/aboutFragment" />

ในที่นี้ใส่ภายใน <fragment ../> ของ MainFragment เพราะมี action click ที่ MainFragment และต้องระบุ app:destination (screen ที่ต้องการเปิด) คือ AboutFragment และกำหนด id ให้กับ action

หรือ ใส่ action ใน editor โดยลากเส้นจาก destination ต้นทางไปยังปลายทางค่ะ

action line

2. implement NavController ดังนี้

-- MainFragment.kt --aboutButton.setOnClickListener {
findNavController().navigate(
R.id.action_mainFragment_to_aboutFragment
)

}

เสร็จแล้วววว ไม่ยากเลย

ถ้า MainFragment ต้องการ navigate ไปหน้าอื่น เช่น SettingFragment ทำได้โดยเพิ่ม <action …/> ที่ navigation graph และใช้ NavController ในการ navigate ได้เลยค่ะ

<navigation
...>
<fragment
android:id="@+id/mainFragment"
android:name="com.truedigital.workshop.MainFragment"
android:label="Main Fragment"
tools:layout="@layout/fragment_main">
<action
android:id="@+id/action_mainFragment_to_aboutFragment"
app:destination="@id/aboutFragment" />
<action
android:id="@+id/action_mainFragment_to_settingFragment"
app:destination="@id/settingFragment" />
</fragment><fragment
...
.AboutFragment"
... />
<fragment
android:id="@+id/settingFragment"
android:name="com.truedigital.workshop.SettingFragment"
android:label="Setting Fragment"
tools:layout="@layout/fragment_setting" />
</navigation>

มี Animation ด้วยนะ

Credit by ilikesticker

ใส่ Animation ยังไงล่ะ

ใน <action ../> ตามด้านล่างได้เลยค่ะ สามารถ custom animation ได้เองอีกด้วย

<action
android:id="@+id/action_mainFragment_to_aboutFragment"
app:destination="@id/aboutFragment"
app:enterAnim="@anim/slide_in_anim"
app:exitAnim="@anim/slide_out_anim"
app:popEnterAnim="@anim/pop_in_anim"
app:popExitAnim="@anim/pop_out_anim"
/>
  • enterAnim จังหวะเปิด destination ตัวใหม่
  • exitAnim จังหวะปิด destination ปัจจุบัน
  • popEnterAnim จังหวะเปิด destination ตัวก่อนหน้า เมื่อกด back
  • popExitAnim จังหวะ pop destination ปัจจุบันออก เมื่อกด back

ผลลัพธ์

จบแล้วกับการสร้าง Navigation Graph แบบเบื้องต้น ใช้งานง่าย แถมจัดการ fragment transaction ให้อีกด้วย และยังใส่ animation ได้อีก น่าสนใจขนาดนี้
จะไม่ใช้ก็คงไม่ได้แล้วววววว

ฝากติดตาม Part2 เร็วๆนี้ด้วยนะคะ^^

--

--