안드로이드 Navigation 사용하기 (Kotlin)

Ddudduu·2021년 11월 4일
0

안드로이드에서 Navigation 사용하는 방법!
프로젝트 시작할때 항상 하는 일인데 매번 해도 헷갈리고 그래서 문서로 남겨놓아야겠다.

1. gradle 설정하기


안드로이드 스튜디오에서 프로젝트를 만들고 구조를 살펴보면, 빌드 관련 사항들이 Gradle Scripts 에 모여있다.
여기서 주로 사용하는 것들은 build.gradle 인데, 헷갈리게 이름 똑같은 애가 2개 있다.
첫번째 build.gradle 은 Project 수준의 gradle 이고
두번째 build.gradle 은 Module(앱) 수준의 gradle 이다.

<Project 의 build.gradle>

buildscript {
    ext.kotlin_version = "1.5.31"
    ext.nav_version = "2.3.5"

    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath "com.android.tools.build:gradle:7.0.3"
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.31"

        classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

맨 위의 두줄은 dependency 설정할 때 필요한 버전을 변수로 만들어버렸다.
새로 업데이트되어도 변수만 바꿔주면 되니까 아주 편함!
project 의 builde.gradle 에 선언해도, module 의 build.gradle 에서도 사용할 수 있다.

navigation 에서 인자 전달할 때 쓰는 safe-arg 도 우선 추가해놓았다.

<Module 의 build.gradle>

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

safe-arg 관련된 플러그인을 추가하고

buildFeatures {
        dataBinding true
        viewBinding true
    }

android{
}
이렇게 돼있는 부분에 buildFeatures 부분을 추가하면 dataBinding 을 사용할 수 있다.(navigation 과 상관없지만 나는 이것도 같이 사용할거라 추가함!)

dependencies {

    implementation 'androidx.core:core-ktx:1.7.0'
    implementation 'androidx.appcompat:appcompat:1.3.1'
    implementation 'com.google.android.material:material:1.4.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.1'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'

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

dependency 에 navigation-fragment , navigation-ui 들을 추가했다. (밑에 두줄)
요기서 $변수명 으로 버전을 쓰면 아까 선언했던 변수를 가져올 수 있다!

gradle 설정을 바꾼 다음엔 꼭 sync 를 해주자

2. 전환할 fragment 생성하기

res/layout 폴더에 xml 파일을 생성한다.
intro_fragment.xml 과 main_fragment.xml 을 생성해주었다.

intro_fragment.xml

main_fragment.xml

intro_fragment 에서 터치 -> main_fragment 전환 하도록 만들어보려고 한다.

3. 뷰 결합

xml 만 띡 만든다고 화면에 띄워지는게 아니다!
activity 화면 만들고 코틀린 파일 작성했듯이, fragment 화면 만들고 파일에 연결해줘야한다.

class IntroFragment : Fragment() {
  private lateinit var binding: IntroFragmentBinding

  override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    binding = IntroFragmentBinding.inflate(inflater, container, false)
    return binding.root
  }
}

Fragment 에서 뷰를 결합해준다.

⭐️ 데이터 바인딩을 사용하려면, xml 작성할 때 가장 바깥을 <layout> 태그로 감싸줘야한다!! ⭐️
그래야 결합할때 IntroFragmentBinding 같이 xml 파일이름 + Binding 형식의 클래스가 만들어진다.

4. Navigation Graph 생성하기

4-1. res/navigation 디렉토리 생성

res 폴더에 디렉토리를 생성하고 이름을 navigation 으로 설정한다!

navigation 디렉토리 안에 navigation 파일(navigation graph) 을 만들어준다.
이 파일의 이름은 상관 없는데, 디렉토리 이름은 꼭 navigation 이어야함!

4-2. Navigation Graph 생성

Navigation Graph 는 말 그대로 fragment가 어떤 fragment 로 전환되고 이동해야하는지 길을 알려주는 지도인 셈이다.

  • fragment 추가
  <fragment
    android:id="@+id/introFragment"
    android:name="com.example.navigationStudy.scene.IntroFragment"
    android:label="IntroFragment"
    tools:layout="@layout/intro_fragment" />

<fragment> 태그로 fragment 를 추가할 수 있다. id, label 은 원하는 대로 지으면 되고 name 은 아까 생성한 코틀린 파일과 연결짓는 속성이다.
tools:layout 속성으로 xml 파일을 적어주면

아까 생성한 xml 파일이 나타난다!
화면이 몇 개 없을 때는 굳이 없어도 되지만, 화면이 많아질수록 헷갈리기 때문에 난 항상 추가해놓는 편이다.

  • Fragment 연결
    Fragment 를 추가했다면, 이제 Fragment 끼리 연결시켜줘야하는데 넘나 쉬움

    Fragment 를 클릭하면 저렇게 파란색 버튼이 뿅 생기는데
    저걸 잡고 원하는 Fragment 로 드래그한다.
그러면 화살표가 생김! Fragment 연결 완료!

화살표로 표시하기 때문에 아주 직관적이다.
어떤 화면에서 출발해서 어디로 가는지 눈에 잘 들어옴

  • startDestination 지정
    해당 Navigation Graph 의 시작점을 설정해주는 작업이다.
    지도 앱에서 출발점을 정하는 것과 똑같다!
원하는 Fragment 선택하고, 위의 메뉴 중에 집 모양 🏠을 누르면 설정 완료! (Fragment 이름 왼편에 집 표시가 생김)

이거 설정 안하면 앱이 죽는다 (아마도....)

5. Activity 에 navigation Graph 심어주기

맨-처음에 프로젝트 생성 시에 자동으로 추가되는 activity_main.xml 로 돌아온다!
navigation graph 를 여기에 넣어줘야한당.

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.fragment.app.FragmentContainerView 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/navHost"
  android:name="androidx.navigation.fragment.NavHostFragment"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  app:defaultNavHost="true"
  app:navGraph="@navigation/main_navigation"
  tools:context=".MainActivity"></androidx.fragment.app.FragmentContainerView>

FragmentContainerView 는 Fragment 를 위해 customized 된 레이아웃인데, Fragment 전환을 안정적으로 처리할 수 있다는 장점이 있다.

속성을 살펴보면,
app:navGraph 가 아까 만들어놓은 navigation graph 를 설정하는 부분이다.

6. 터치 -> Fragment 전환

intro_fragment.xml 에서 main_fragment.xml 로 이동하게 할 예정!

intro_fragment.xml

 override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    val action: NavDirections = IntroFragmentDirections.actionIntroFragmentToMainFragment()
    binding.root.setOnClickListener {
      view.findNavController().navigate(action)
    }
  }

이 함수는 처음에 만든 함수랑 다르다! onViewCreate() 임.. 헷갈리지 말자!

아무튼, navigation graph 에서 intro -> main 으로 방향을 설정했는데,
val action: NavDirections = IntroFragmentDirections.actionIntroFragmentToMainFragment()
여기가 방향을 가져오는 부분이다.

intro 화면에서 아무데나 누르면 이동하도록, 클릭리스너 안에서
view.findNavController().navigate(action)
해당 화살표 방향으로 이동하도록 해줌!


‼️결과는 다음과 같다.

귀여운 춘식이가 짠-!
기염둥이 춘식이는 프렌즈샵에서 주어옴 큐티 ㅠ.ㅠ





전체 코드는

여기! 에서 확인 가능합니당.

velog 에서는 아직 이미지 크기 조절이 안되나보다. 미리보기에선 적용되는데 작성하고 나면 겁나 큼 😭

profile
Android

0개의 댓글