Android

Navigation Component(1)

smomo 2021. 5. 18. 16:02

Android Jetpack의 Navigation Componet는 단순한 버튼 클릭부터 좀 더 복잡한 패턴(앱바, 탐색 창)에 이르기까지 여러 가지 탐색을 구현하도록 도와준다.

1. Navigation Component 장점

  • fragment transactions 자동 처리
  • 올바른 up, back 처리
  • animations 및 transactions에 표준화된 리소스 제공
  • 딥 링크 구현 및 처리
  • 추가 작업 없이 탐색 UI 패턴(예: 탐색창, 하단 탐색 메뉴) 구현
  • Safe Args 
  • Android Studio에서 앱의 탐색 흐름을 시각화하고 수정 가능

2. Navigation 구성요소

  • Navigation graph 

사용자가 앱에서 선택할 수 있는 가능한 모든 경로를 정의하는 XML Resource이다. 

지정된 대상에서 도달할 수 있는 모든 대상을 시각적으로 표시한다.

Android Studio에서는 Navigation Editor에 그래프를 표시한다.

 

대상이 3개인 Navigation Graph

  • NavHostFragment(Layout XML View)

Navigation graph에서 대상을 표시하는 빈 컨테이너

 

  • NavController 

Navigation graph내에서 현재 위치를 계속 추적하는 객체.

탐색 시 이동하려는 위치나 Navigation Graph에서 선택할려는 경로를 알려주면 NavHostFragment에 적절한 대상(Destinations)을 표시한다.

3. 환경 설정

build.gradle 파일에 다음 dependencies를 추가

dependencies {
  def nav_version = "2.3.5"

  // Java language implementation
  implementation "androidx.navigation:navigation-fragment:$nav_version"
  implementation "androidx.navigation:navigation-ui:$nav_version"

  // Kotlin
  implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
  implementation "androidx.navigation:navigation-ui-ktx:$nav_version"

  // 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-alpha10"
}

4. 탐색 그래프(Navigation graph) 만들기

Project창에서 res 디렉토리를 마우스 오른쪽 버튼으로 클릭하고 New > Android Resource File을 선택한다. 

File name 필드에 resource file 이름을 입력, Resource type 드롭다운 목록에서 Navigation을 선택한다.

Navigation Editor의 Code탭을 클릭하면 아래와 비슷한 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"
    android:id="@+id/nav_graph">
</navigation>

5. NavHostFragment 추가

<?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="ndroidx.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를 탐색 그래프와 연결한다.

app:defaultNavHost = "true" 속성을 사용하면 NavHostFragment가 시스템 백버튼을 가로챈다. 동일한 레이아웃에 여러 Host가 있어도 한 NavHost만 기본으로 지정할 수 있다.

6. 탐색 그래프에 대상(Destinations) 추가

기존 Fragment, Activity를 이용해서 또는 Navigation Editor를 사용하여 새로운 대상(Destinations)을 만들거나 교체할 수 있다.

<?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"
    app:startDestination="@id/home_dest">
    <fragment
        android:id="@+id/home_dest"
        android:name="test.com.navigation.HomeFragment"
        android:label="Home"
        tools:layout="@layout/home_fragment">
    </fragment>
    <fragment
        android:id="@+id/flow_step_one_dest"
        android:name="test.com.navigation.FlowStepFragment"
        android:label="Step_1"
        tools:layout="@layout/flow_step_one_fragment">
        <argument
            android:name="flowStepNumber"
            android:defaultValue="1"
            app:argType="integer" />
        <action
            android:id="@+id/next_action"
            app:destination="@id/flow_step_two_dest" />
    </fragment>

    <fragment
        android:id="@+id/flow_step_two_dest"
        android:name="test.com.navigation.FlowStepFragment"
        android:label="Step_2"
        tools:layout="@layout/flow_step_two_fragment">
        <argument
            android:name="flowStepNumber"
            android:defaultValue="2"
            app:argType="integer" />
        <action
            android:id="@+id/next_action"
            app:destination="@id/home_dest" />
    </fragment>
</navigation>

app:startDestination 속성은 시작 대상(Destinations) 설정

android:name 속성은 대상(Destinations) 구현 클래스 이름

  • argument 

대상(Destinations)간의 인수값 정의

 

인수 이름, 인수 유형, 인수의 null 허용 여부 및 필요하다면 default값을 입력하여 정의한다.

 

코드에선 getArguments() 메서드를 사용하여 Bundle을 검색하여 데이터 사용

        val flowStepNumber = arguments?.getInt("flowStepNumber")
        Log.d(TAG, "flowStepNumber = $flowStepNumber")

자세한 내용은 https://developer.android.com/guide/navigation/navigation-pass-data 페이지 참조

References