본문 바로가기

Android/Jetpack, Clean Architecture

[Android] AAC Navigation 사용하기 (이동, 데이터 전송, 애니메이션)

이전에 Navigation의 구성요소, 원칙 등을 살펴봤습니다.

이번에는 Navigation을 사용해 Fragment 간에 이동, 데이터 전송, 애니메이션 등을 구현할 것입니다.

 

결과

총 5개의 Fragment를 이동할 것이며 이름, 이메일 문자열을 데이터로 전송할 것입니다.

 

의존성 선언

build.gradle (app or module) 

dependencies {
  def nav_version = "2.3.3"

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

 

Navigation 구성요소에는 Safe Args라는 Gradle 플러그인이 있습니다.

Safe Args는 모든 연결된 arguments에 유형 안전성을 갖춘 탐색 및 액세스를 하기 위한 간단한 객체 및 빌더 클래스를 생성합니다.

Safe Args는 유형 안전성을 보장하기 때문에 navigating 할 때나 데이터를 전달할 때 강력히 권장됩니다.

 

build.gradle (project)

buildscript {
    repositories {
        google()
    }
    dependencies {
        def nav_version = "2.3.3"
        classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
    }
}

 

build.gradle (app or module)

apply plugin: "androidx.navigation.safeargs.kotlin"
// for Java
apply plugin: "androidx.navigation.safeargs"

 

(선택) DataBinding을 사용할 것이므로 DataBinding도 추가합니다.

build.gradle (app or module)

buildFeatures {
    dataBinding true
}

 

 

nav_graph xml 파일을 만듭니다.

Navigation XML은 res/navigation/ 폴더에 추가해줍니다.

 

메인 액티비티에 NavHostFragment View를 추가합니다.

NavHostFragment를 이름으로 가진 Fragement라는 것을 알 수 있습니다.

default NavHost라는 것을 알 수 있고, 이전에 만든 nav graph.xml의 경로도 알 수 있습니다.

<fragment
        android:id="@+id/fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        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" />

 

nav_graph.xml에서 Fragment(destination)들을 생성 및 설정합니다.

 

각각의 Fragment는 하나의 화면인 Destination을 의미합니다.

Fragment를 추가하고 각각에 맞는 View를 추가하면 다음과 같이 Visual Editor에 추가한 Fragment가 나옵니다.

 

 XML 코드를 보면 nav_graph의 최상위 태그는 navigation입니다.

nav_graph의 id와 첫 시작 destination fragment에 대한 설정이 있습니다.

<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/homeFragment">

 

다음은 Fragment 태그입니다.

name 속성에서 해당하는 Fragment의 패키지가 지정됩니다.

tools:layout에는 Design Tool에서 보이는 레이아웃의 파일이 지정됩니다.

<fragment
        android:id="@+id/homeFragment"
        android:name="com.keepseung.navdemo.HomeFragment"
        android:label="HomeFragment"
        tools:layout="@layout/fragment_home"/>

 

아래는 navigation XML에서 사용할 수 있는 기본 태그입니다. 

  • <navigation> : NavGraph
  • <fragment> or <activity> : NavDestination
  • <action> : NavAction (handled in NavDirections)
  • <argument> : NavArgs

 

Fragment끼리 이동하는 것을 의미하는 action을 지정합니다.

Visual Editor에서 fragment를 마우스로 드래그엔 드롭하면 action을 지정할 수 있습니다.

fragment에 마우스로 드래그엔 드랍하면 action을 지정할 수 있습니다.

 

 

nav_host XML 코드 중 action 태그는 Fragment 태그에 속합니다.

action태그는 다음처럼 id와 destination 속성이 선언됩니다.

action의 id는 직관적으로 "action_이동 전 Fragment_to_이동 대상 Fragment"의 규칙으로 만들어집니다.

action의 destination은 이동 대상 Fragment id가 지정됩니다.

<fragment
       	android:id="@+id/homeFragment"
        '''>
        <action
            android:id="@+id/action_homeFragment_to_nameFragment"
            app:destination="@id/nameFragment"/> 
        />

 

NavController를 사용해 Fragement 간에 이동하는 코드를 작성합니다

NavController를 사용해 Fragement 간에 이동하는 코드를 작성합니다. NavController를 사용해 Fragement 간에 이동이 발생합니다.

HomeFragment.kt

binding.signUpButton.setOnClickListener {
	it.findNavController().navigate(R.id.action_homeFragment_to_nameFragment)
}
binding.termsButton.setOnClickListener {
	it.findNavController().navigate(R.id.action_homeFragment_to_termsFragment)
}


 

다음은 A Fragment에서 B Fragment로 이동하는 것을 보여주는 구조 도입니다.

Android Navigation Architecture

 

Fragment를 이동하면서 데이터를 전달할 경우 Bundle을 사용합니다.

  • 보낼 때
binding.nextButton.setOnClickListener {
	val bundle = bundleOf("name" to binding.nameEditText.text.toString())
	it.findNavController().navigate(R.id.action_nameFragment_to_emailFragment,bundle)
}

 

  • 2개 이상의 데이터를 보낼 경우
binding.nextButton.setOnClickListener {
	val bundle = bundleOf("email" to email, "name" to name)
	it.findNavController().navigate(R.id.action_nameFragment_to_emailFragment,bundle)
}

 

  • 받을 때
val arg = requireArguments()
val name = arg.getString("name")

 

action에 사용되는 animation을 지정합니다.

action에 사용되는 animation은 다음 이미지와 같이 4가지를 지정할 수 있습니다.

  • enterAnim : action 실행시, 이동할 Destination에 대한 애니메이션
  • exitAnim : action을 실행할 때 현재 Destination에 대한 애니메이션
  • popEnterAnim : 이전 화면으로 돌아갈 때(Pop or Back) 이동할 BackStack의 Destination에 대한 애니메이션
  • popExitAnim : 이전 화면으로 돌아갈 때(Pop or Back) 종료되는 현재 Destincation 에 대한 애니메이션

 

전체 소스 : github.com/keepseung/Android-Blog-Source

 

keepseung/Android-Blog-Source

https://develop-writing.tistory.com/ 에서 제공하는 예제. Contribute to keepseung/Android-Blog-Source development by creating an account on GitHub.

github.com

 

다음 글

참고 : developer.android.com/guide/navigation/navigation-pass-data?hl=en#Safe-args

developer.android.com/guide/navigation

fornewid.medium.com/navigation-%ED%9B%91%EC%96%B4%EB%B3%B4%EA%B8%B0-82d23fbc85af

namjackson.tistory.com/28