my repository

Android :: JetPack - AAC Navigation Component ์‚ฌ์šฉ๋ฒ• ๋ณธ๋ฌธ

IT/Android (Kotlin)

Android :: JetPack - AAC Navigation Component ์‚ฌ์šฉ๋ฒ•

hjin 2022. 2. 22. 21:56

๐Ÿ’กNavigation

 

Navigation

Android JetPack ์˜ AAC ์ปดํฌ๋„ŒํŠธ ์ค‘ ๋„ค๋น„๊ฒŒ์ด์…˜์€ ์•ฑ ๋‚ด์˜ ํ™”๋ฉด ์ด๋™ ๊ตฌํ˜„์„ ๋„์™€์ฃผ๋Š” ์ปดํฌ๋„ŒํŠธ์ด๋‹ค.

์‹œ๊ฐ์ ์œผ๋กœ view๋“ค์ด ์–ด๋–ป๊ฒŒ ์—ฐ๊ฒฐ๋˜์–ด ์žˆ๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ์–ด ์•ฑ์˜ ์ „๋ฐ˜์ ์ธ ํ๋ฆ„์„ ํŒŒ์•…ํ•˜๊ธฐ ์‰ฝ๊ณ , flow ์ˆ˜์ •์ด ์šฉ์ดํ•˜๋‹ค.

๋”ฐ๋ผ์„œ, single Activity - multiple Fragment ๊ตฌ์กฐ๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ ์‰ฝ๊ฒŒ ํ•ด์ค€๋‹ค.

 

Navigation์„ ์‚ฌ์šฉํ•˜์—ฌ ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ๋“ค

  • Fragment ํŠธ๋žœ์žญ์…˜์„ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.
  • Up, Back ๋ฒ„ํŠผ์˜ ์ž‘์—… ๋“ฑ(๋ฐฑ ์Šคํƒ ๊ด€๋ฆฌ)์„ ๊ฐ„๋‹จํ•˜๊ฒŒ ์ฒ˜๋ฆฌ
  • ํ™”๋ฉด ์ „ํ™˜ ์‹œ, Animation์ด๋‚˜ Transition์„ ์œ„ํ•œ ํ‘œ์ค€ํ™”๋œ ๋ฆฌ์†Œ์Šค๋ฅผ ์ œ๊ณต
  • ๋”ฅ๋งํฌ ๊ตฌํ˜„ ๋ฐ ์ฒ˜๋ฆฌ๋ฅผ ์‰ฝ๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • Navigation UI ํŒจํ„ด์„ ์‚ฌ์šฉํ•œ Navigation drawers, Bottom Navigation์˜ ์—ฐ๋™์„ ์‰ฝ๊ฒŒ ๊ตฌํ˜„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ์ง€์›
  • fragment ๊ฐ„์˜ ์ด๋™ ์‹œ ์•ˆ์ „ํ•˜๊ฒŒ ๋ฐ์ดํ„ฐ ์ „๋‹ฌ ๊ฐ€๋Šฅ
  • Navigation Editor๋ฅผ ํ†ตํ•ด ํ™”๋ฉด ํ๋ฆ„์„ ์‹œ๊ฐ์ ์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ViewModel - Navigation Graph์— ๋Œ€ํ•œ ViewModel์„ ํ™•์ธํ•ด ๊ทธ๋ž˜ํ”„ ๋Œ€์ƒ ์‚ฌ์ด์— UI ๊ด€๋ จ ๋ฐ์ดํ„ฐ๋ฅผ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๊ธฐ์กด FragmentManager, Intent, Bundle ๋“ฑ์˜ ์‚ฌ์šฉ์„ ๋Œ€์ฒดํ•  ์ˆ˜ ์žˆ๋‹ค.

 

Navigation์˜ ๊ตฌ์„ฑ์š”์†Œ

  • Navigation Graph : ๋ชจ๋“  Navigation ๊ด€๋ จ ์ •๋ณด๊ฐ€ ํ•˜๋‚˜์˜ ์ค‘์‹ฌ ์œ„์น˜์— ๋ชจ์—ฌ ์žˆ๋Š” XML ๋ฆฌ์†Œ์Šค์ด๋‹ค. ์ฆ‰, ์‚ฌ์šฉ์ž๊ฐ€ ์•ฑ์—์„œ ๊ฐˆ ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ํ”Œ๋กœ์šฐ๋ฅผ ๋ณด์—ฌ์ฃผ๊ณ  ์•ฑ ๋‚ด์˜ Fragment๋ฅผ ํ•œ ๋ˆˆ์— ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. Destination ๋ชฉ๋ก์„ ๊ฐ–๊ณ  ์žˆ๋Š” ๋ถ€๋ถ„.
  • NavHost : Navigation Graph์—์„œ ๋Œ€์ƒ์„ ํ‘œ์‹œํ•˜๋Š” ๋นˆ ์ปจํ…Œ์ด๋„ˆ. (NavController๋ฅผ ๊ฐ–๊ณ  ์žˆ๋Š” ์ปจํ…Œ์ด๋„ˆ) ๋Œ€์ƒ ๊ตฌ์„ฑ์š”์†Œ์—๋Š” ํ”„๋ž˜๊ทธ๋จผํŠธ ๋Œ€์ƒ์„ ํ‘œ์‹œํ•˜๋Š” ๊ธฐ๋ณธ NavHost ๊ตฌํ˜„์ธ NavHostFragment๊ฐ€ ํฌํ•จ๋œ๋‹ค.
  • NavController : NavHost์—์„œ App Navigation์„ ๊ด€๋ฆฌํ•˜๋Š” ๊ฐ์ฒด. ์‚ฌ์šฉ์ž๊ฐ€ ์•ฑ ๋‚ด์—์„œ ์ด๋™ํ•  ๋•Œ NavHost์—์„œ ๋Œ€์ƒ ์ฝ˜ํ…์ธ ์˜ ์ „ํ™˜์„ ์กฐ์ข…ํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค. ์ฆ‰, Navigation Graph๋ฅผ ๋‹ค๋ฃจ๋Š” ๋ถ€๋ถ„.

 

=> Navigation Graph์—์„œ ํŠน์ • ๊ฒฝ๋กœ๋ฅผ ๋”ฐ๋ผ ์ด๋™ํ• ์ง€, ํŠน์ • ๋Œ€์ƒ์œผ๋กœ ์ง์ ‘ ์ด๋™ํ• ์ง€ NavController์—๊ฒŒ ์ „๋‹ฌํ•˜๊ณ , NavController๊ฐ€ NavHost์— ์ ์ ˆํ•œ ๋Œ€์ƒ์„ ํ‘œ์‹œํ•ด์ฃผ๋Š” ๋ฐฉ์‹

Navigation Interface Overview

 
FragmentNavigator / ActivityNavigator / NavGraphNavigator
 

 

0. dependency

dependencies {
  
  // Kotlin
  implementation("androidx.navigation:navigation-fragment-ktx:$nav_version")
  implementation("androidx.navigation:navigation-ui-ktx:$nav_version")

}

 

* Safe Args ์ถ”๊ฐ€ (Optional)

// ์ตœ์ƒ์œ„ build.gradle
buildscript {
    ext {
        nav_version = '2.4.1'
    }
    repositories {
        google()
    }
    dependencies {
        classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
    }
}
// app or module build.gradle
plugins {
    id 'androidx.navigation.safeargs.kotlin'
}

 

1. Navigation Graph

๋ชจ๋“  ๋„ค๋น„๊ฒŒ์ด์…˜ ๊ด€๋ จ๋œ ์ •๋ณด๋ฅผ ๊ฐ€์ง„ res/navigation ํด๋”์˜ XML resource ํŒŒ์ผ์ด๋‹ค.

ํ™”๋ฉด ์ด๋™์— ๋Œ€ํ•œ ๋ชจ๋“  ์ •๋ณด(Action, ํ™”๋ฉด ์ด๋™ ์‹œ ํŒŒ๋ผ๋ฏธํ„ฐ, ํ™”๋ฉด ๋‹จ์œ„)๋ฅผ ์ •์˜ํ•˜๋Š” ๊ณณ์ด๋‹ค.

๊ฐ๊ฐ์˜ ์Šคํฌ๋ฆฐ๋“ค์€ ๋Œ€์ƒ(Destination / ๋ชฉ์ ์ง€๊ฐ€ ๋˜๋Š” ํ•˜๋‚˜์˜ ํ™”๋ฉด)์ด๋ผ๋Š” ์ด๋ฆ„์„ ๊ฐ–๊ณ  ์žˆ๊ณ , ๊ฐ€๊ณ ์‹ถ์€ ๊ณณ์œผ๋กœ ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

 

[ Navigation xml ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋ณธ ํƒœ๊ทธ ]

  • <navigation> : NavGraph์˜ ๊ธฐ๋ณธ ํƒœ๊ทธ
  • <fragment> or <Activity> or <Dialog> ๋“ฑ์˜ Destination
  • <action> : ํ™”๋ฉด ์ด๋™์— ๋Œ€ํ•œ ์•ก์…˜ ์ •์˜, ๊ทธ๋ž˜ํ”„์—์„œ๋Š” ํ™”์‚ดํ‘œ๋กœ ํ‘œํ˜„๋œ๋‹ค.
  • <argument> : ํ™”๋ฉด ์ด๋™์— ๋Œ€ํ•œ ํŒŒ๋ผ๋ฏธํ„ฐ ์ •์˜
  • <deeplink> : ๋”ฅ๋งํฌ์— ๋Œ€ํ•œ ๋‚ด์šฉ์„ ์ •์˜

 

[ ์‹ค์Šต ]

1) res > New > Android Resource File

2) File name ์ž…๋ ฅ

3) Resource type > Navigation > OK

4) fragment ์ƒ์„ฑ

5) nav_graph์—์„œ Fragment๋ฅผ ๋“œ๋ž˜๊ทธํ•ด์„œ ๋‹ค๋ฅธ Fragment์— ์—ฐ๊ฒฐ

 

 

<?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_library"
    app:startDestination="@id/homeViewPagerFragment">

    <fragment
        android:id="@+id/homeViewPagerFragment"
        android:name="com.example.libraryproject.HomeViewPagerFragment"
        android:label="fragment_view_pager"
        tools:layout="@layout/fragment_view_pager" >
        <action
            android:id="@+id/action_homeViewPagerFragment_to_bookDetailFragment2"
            app:destination="@id/bookDetailFragment" />
    </fragment>
    <fragment
        android:id="@+id/bookDetailFragment"
        android:name="com.example.libraryproject.BookDetailFragment"
        android:label="fragment_book_detail"
        tools:layout="@layout/fragment_book_detail" >
        <action
            android:id="@+id/action_bookDetailFragment_to_libraryFragment2"
            app:destination="@id/libraryFragment" />
    </fragment>
    <fragment
        android:id="@+id/libraryFragment"
        android:name="com.example.libraryproject.LibraryFragment"
        android:label="fragment_library"
        tools:layout="@layout/fragment_library" />
</navigation>

 

2. NavHost

Navigation Graph์— ์ •์˜๋œ ํ™”๋ฉด๋“ค์„ ๋ณด์—ฌ์ฃผ๋Š” ์ปจํ…Œ์ด๋„ˆ์˜ ์—ญํ• ์„ ํ•œ๋‹ค.

ํ™”๋ฉด์ด๋™์— ๋Œ€ํ•œ ์•ก์…˜์€ ๋ชจ๋‘ NavHost๋ผ๋Š” Fragment์—๊ฒŒ ์œ„์ž„๋œ๋‹ค.

์ผ๋ฐ˜ Fragment์˜ Name์— NavHostFragment๋ฅผ ์ •์˜ํ•ด์ฃผ๊ณ , ์—ฐ๊ฒฐ๋˜๋Š” navGraph๋„ ์ •์˜ํ•ด์ฃผ์–ด์•ผํ•œ๋‹ค.

 

[ ์‹ค์Šต ]

1) activity_main.xml ํŒŒ์ผ์— NavHostFragment ์ถ”๊ฐ€

2) name / defaultNavHost / navGraph ์†์„ฑ ์ถ”๊ฐ€

<androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:defaultNavHost="true"
        app:navGraph="@navigation/nav_library"/>

์—ฌ๊ธฐ๊นŒ์ง€ ํ•˜๋ฉด ์ด์ œ ํ•˜๋‚˜์˜ ์•กํ‹ฐ๋น„ํ‹ฐ + ์—ฌ๋Ÿฌ ๊ฐœ์˜ ํ”„๋ž˜๊ทธ๋จผํŠธ ๊ตฌ์กฐ๊ฐ€ ๋งŒ๋“ค์–ด์ง„ ๊ฒƒ์ด๋‹ค.

 

3. NavController

ํ™”๋ฉด์ด๋™์— ๋Œ€ํ•œ ์ปจํŠธ๋กค๋Ÿฌ ์—ญํ• ์„ ํ•œ๋‹ค.

NavHost์—์„œ ์–ป์„ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์•„๋ž˜์™€ ๊ฐ™์€ ๋ฐฉ๋ฒ•์„ ํ†ตํ•ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด ๋ฒ„ํŠผ์„ ํ†ตํ•ด ํ™”๋ฉด์„ ์ด๋™ํ•˜๋Š” ๊ฒฝ์šฐ, ๋ฒ„ํŠผ์— setOnClickListener๋ฅผ ์‚ฌ์šฉํ•ด์ฃผ๋Š” '์•ก์…˜'์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

<!--navController fragment,activity,view์—์„œ find -->
 val navController = findNavController()
 
 <!--navController navhost id๋กœ ๊ฐ€์ ธ์˜ค๊ธฐ -->
 val navController = findNavController(R.id.nav_container)
 
 <!--navController - navhost์—์„œ ๊ฐ€์ ธ์˜ค๊ธฐ -->
 val host: NavHostFragment = supportFragmentManager
                .findFragmentById(R.id.my_nav_host_fragment) as NavHostFragment? ?: return
 val navController = host.navController
binding.toolbar.setNavigationOnClickListener { view ->
    view.findNavController().navigateUp()
}