JY-Dev Tech Blog

안드로이드(Android) - Navigation 사용법 본문

안드로이드/레이아웃

안드로이드(Android) - Navigation 사용법

JY-Dev 2020. 11. 9. 13:28

[OverView]

이번에는 Navigation에 대해 알려드리겠습니다.

Navigation는 iOS개발에서 사용하는 스토리보드와 흡사합니다. Fragment간의 플로우를 시각적으로 볼수 있다는 특징이 있어 앱 플로우를 보거나 할때 유용하게 쓰일 수 있습니다.

 

[Navigation 구성요소]

  • Navigation Graph : 모든 Navigation 관련 정보가 하나의 중심 위치에 모여 있는 XML 리소스입니다. 단순히 말해 사용자가 앱에서 갈 수 있는 모든 플로우를 보여주고 앱내의 Fragment를 한눈에 확인 할 수 있습니다.
  • NavHost : Navigation Graph에서 대상을 표시하는 빈 컨테이너입니다. 대상 구성요소에는 프래그먼트 대상을 표시하는 기본 NavHost 구현인 NavHostFragment가 포함 됩니다.
  • NavController : NavHost에서 App Navigation을 관리하는 객체입니다. NavController는 사용자가 앱 내에서 이동할 때 NavHost에서 대상 콘텐츠의 전환을 조종하는 역활을 합니다.

Navigation Graph에서 특정 경로를 따라 이동할지, 특정 대상으로 직접 이동할지 NavController에게 전달하고 NavController가 NavHost에 적절한 대상을 표시해주는 방식입니다.

 

[장점]

  • 프래그먼트의 트렌젝션 처리.
  • 올바르게 Up과 Back동작을 처리.
  • 화면전환에 대한 표준화된 애니메이션 리소스.
  • 딥 링크 구현 및 처리를 쉽게 할 수 있다.
  • Bottom Navigation과 같은 요소들을 최소한의 추가작업으로 구현.
  • Safe Args - 대상사이에서 데이터를 탐색하고 전달할때 안정성을 제공하는 Graph 플러그인.
  • ViewModel - Navigation Graph에 대한 ViewModel을 확인해 그래프 대상 사이에 UI 관련 데이터를 공유.

[build.gradle]

   // Feature module Support
    implementation "androidx.navigation:navigation-dynamic-features-fragment:$nav_version"

    // Testing Navigation
    androidTestImplementation "androidx.navigation:navigation-testing:$nav_version"

    // Jetpack Compose Integration
    implementation "androidx.navigation:navigation-compose:1.0.0-alpha01"

3가지 라이브러리를 추가해주도록 합시다.

 

[Create Navigation Graph]

  1. Project 창에서 res 디렉터리를 마우스 오른쪽 버튼으로 클릭하고 New > Android Resource File을 선택합니다. New Resource File 대화상자가 나타납니다.

  2. File name 필드에 'nav_graph'와 같은 이름을 입력합니다.

  3. Resource type 드롭다운 목록에서 Navigation을 선택한 후 OK를 클릭합니다.

제대로 완료 하셨다면 이런 창이 뜨게 됩니다.

일단 테스트를 위해 Fragment 2개를 생성해주도록 합시다 저는 fragment_blankfragment_blank2라는 Fragment를 만들어 주었습니다.

 

[nav_graph.xml]

<?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">


    <fragment
        android:id="@+id/blankFragment"
        android:name="com.jydev.navicontrollex.BlankFragment"
        android:label="fragment_blank"
        tools:layout="@layout/fragment_blank">
    </fragment>

    <fragment
        android:id="@+id/blankFragment02"
        android:name="com.jydev.navicontrollex.BlankFragment2"
        android:label="fragment_blank2"
        tools:layout="@layout/fragment_blank2"/>
</navigation>

 

id는 편한대로 설정하면되고 name에는 그 Fragment의 이름을 넣어줘야합니다. 그리고 tools:layout에는 그 Fragment의 layout을 지정해 주도록 합시다. (label은 선택사항)

 

그렇게 되면 Design탭에 들어가게되면 이런식으로 화면상에 Frament 2개가 생성이 됩니다.

 

왼쪽 하단에 있는 Component Tree에서 Start Destination을 지정해줄 수 있는데 이건 처음에 표시해줄 Fragment를 설정해 줍니다. 만약 Start Destination지정을 안해주면 에러가 발생하게 되니깐 꼭 지정해주면됩니다. 

Start Destination을 지정해줄 Fragmemt에 우클릭 후 Set as Start Destination을 클릭해주면 선택한 Fragment에 Start Destination 지정이 됩니다.

 

이렇게 nav_graph에서 Fragment를 선택해주면 오른쪽 중앙에 파란색 원이 생기는데 이걸 드래그해서 다른 Fragment에 연결을 해주게 되면 다른 Fragment에 대한 Action을 지정 해줄 수 있습니다. 또한 Componet Tree에서 Action을 지정해줄 Fragment에 우클릭 후 Add Action을 통해 Action을 지정해 줄 수 있습니다.

 

이 Action을 통해 이동할 Fragment를 지정하거나 Data를 넘겨줄 수 있습니다.

 

화살표가 생기게 되는데 이는 Action을 나타냅니다. 

화살표를 클릭하여 작업을 강조표시합니다. 다음 속성은 Attributes 패널에 표시됩니다.

  • Type 필드에는 '작업'이 포함됩니다.

  • ID 필드에는 작업의 ID가 포함됩니다.

  • Destination 필드에는 대상 프래그먼트 또는 활동의 ID가 포함됩니다.

Attributes에서 Animation을 설정해주거나 Launch Options를 설정 등등 여러가지 Action에한 설정을 해주실 수 있습니다.

 

 

다 완료가 되었다면 이 nav_graph를 표시해줄 Activity에서 FragmnentContainerView를 통해 이 graph를 보여 줄 수 있습니다. 

 

[activity_main.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">

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:defaultNavHost="true"
        app:navGraph="@navigation/nav_graph" />


</androidx.constraintlayout.widget.ConstraintLayout>

다음 내용을 참고하세요.

  • android:name 속성은 NavHost 구현의 클래스 이름을 포함합니다.

  • app:navGraph 속성은 NavHostFragment를 탐색 그래프와 연결합니다. 탐색 그래프는 사용자가 이동할 수 있는 이 NavHostFragment의 모든 대상을 지정합니다.

  • app:defaultNavHost="true" 속성을 사용하면 NavHostFragment가 시스템 뒤로 버튼을 가로챕니다. 하나의 NavHost만 기본값으로 지정할 수 있습니다. 동일한 레이아웃에 여러 호스트가 있다면(예: 창이 2개인 레이아웃) 한 호스트만 기본 NavHost로 지정해야 합니다.

또한 다음과 같은 방법으로 Layout Editor를 사용하여 NavHostFragment를 활동에 추가할 수 있습니다.

  1. 프로젝트 파일 목록에서 활동의 레이아웃 XML 파일을 더블클릭하여 Layout Editor에서 엽니다.

  2. Palette 창 내에서 Containers 카테고리를 선택하거나 'NavHostFragment'를 검색합니다.

  3. 활동으로 NavHostFragment 뷰를 드래그합니다.

  4. 다음으로, 표시되는 Navigation Graphs 대화상자에서 해당 탐색 그래프를 선택하여 이 NavHostFragment와 연결한 후 OK를 클릭합니다.

대상으로 이동하는 것은 NavHost 내에서 앱 탐색을 관리하는 객체인 NavController를 사용하여 실행됩니다. 각 NavHost에는 해당하는 자체 NavController가 있습니다. 다음 메서드 중 하나를 사용하여 NavController를 검색할 수 있습니다.

 

androidx.navigation  |  Android 개발자  |  Android Developers

Content and code samples on this page are subject to the licenses described in the Content License. Java is a registered trademark of Oracle and/or its affiliates. Last updated 2020-07-22 UTC.

developer.android.com

FragmentContainerView를 사용하여 NavHostFragment를 만들 때 또는 FragmentTransaction을 통해 NavHostFragment를 활동에 수동으로 추가할 경우 Navigation.findNavController(Activity, @IdRes int)를 통해 활동의 onCreate()에서 NavController를 검색하려고 하면 실패합니다. 대신 NavHostFragment에서 직접 NavController를 검색해야 합니다.

 

val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
val navController = navHostFragment.navController

 

 

[Safe Args]

대상 간 이동을 위해 Safe Args Gradle 플러그인을 사용하는 것이 좋습니다. 이 플러그인은 대상 간 유형 안전 탐색 및 인수 전달을 사용 설정하는 간단한 객체 및 빌더 클래스를 생성합니다.

 

[설명]

Safe Args를 사용 설정하면 생성된 코드에 정의한 작업의 클래스 및 메서드와 각 발신 및 수신 대상에 상응하는 클래스가 포함됩니다.

Safe Args는 작업이 발생하는 각 대상의 클래스를 생성합니다. 생성된 클래스 이름은 발신 대상 클래스 이름에 'Directions'를 붙입니다. 예를 들어, 발신 대상 이름이 SpecifyAmountFragment라면 생성된 클래스 이름은 SpecifyAmountFragmentDirections가 됩니다.

생성된 클래스에는 발신 대상에서 정의한 각 작업의 정적 메서드가 포함됩니다. 이 메서드는 정의된 모든 작업매개변수 를 인수로 사용하고 navigate()에 직접 전달할 수 있는 Navdirections객체를 반환합니다.

 

[build.gradle]

 

dependencies {
        classpath "com.android.tools.build:gradle:4.1.0"
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        
        //Navigation Controller
        def nav_version = "2.3.1"
        classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
    }

build 그래들에 의존성을 추가해줍시다.

plugins {
    id 'com.android.application'
    id 'kotlin-android'
    id 'androidx.navigation.safeargs.kotlin'
}

플러그인을 추가 해줍시다.

※ AndroidX 이전에 따라 gradle.properties파일에 android.useAndroidX=true가 있어야 합니다.

 

Safe Args를 사용하게 되면 Action을 지정해준 Fragment이름 + Directions이라는 클래스가 자동으로 생성됩니다. 

그래서 생성된 BlankFragmentDirections에서 Action을 호출해 NavController로 그 액션을 수행해주면 됩니다.

button.setOnClickListener {
            val action = BlankFragmentDirections.actionBlankFragmentToBlankFragment022()
            it.findNavController().navigate(action)
        }

이렇게 되면 Button을 클릭하면 생성해 두었던 Action인 actionBlankFragmentToBlankFragment022()을 NavController를 통해 호출합니다.

 

Comments