📱 Android

[Jetpack] Navigation Component #1 기본 뼈대 만들기

콩드로이드 2023. 4. 30. 18:54

Jetpack에서 Navigation을 한번 사용해보겠습니다

Navigation에 관해선 아래의 공식문서를 참고했어요  

https://developer.android.com/guide/navigation

 

탐색  |  Android 개발자  |  Android Developers

Android Jetpack의 탐색 구성요소를 사용하여 앱에서 탐색 구현

developer.android.com


Navigation에는 3가지 Key part가 있습니다

 

1️⃣ Navigation Graph

모든 네비게이션 관련 정보가 한곳에 모여 있는 XML 리소스

앱을 통해 이동할 수 있는 경로뿐만 아니라 앱 내의 모든 개별 콘텐츠 영역(목적지)가 포함됩니다

 

2️⃣ Nav Host

Navigation graph로부터 목적지들을 표시하는 빈 컨테이너입니다

프래그먼트 목적지를 표시하는 기본 NavHost 구현인 NavHostFragment가 Navigation 구성요소에 포함됩니다

 

3️⃣ Nav Controller

NavHost 내에서 Navigation을 관리하는 객체입니다

NavController는 사용자가 앱 내에서 이동 시 NavHost에서 목적지 변경을 조정합니다

 

 

 

💡 Navigation의 장점

  • Handling fragment transactions.
  • Handling Up and Back actions correctly by default.
  • Providing standardized resources for animations and transitions.
  • Implementing and handling deep linking.
  • Including Navigation UI patterns, such as navigation drawers and bottom navigation, with minimal additional work.
  • Safe Args - a Gradle plugin that provides type safety when navigating and passing data between destinations.
  • ViewModel support - you can scope a ViewModel to a navigation graph to share UI-related data between the graph's destinations.

 


0. 라이브러리 추가 

dependencies {
  val nav_version = "2.5.3"

  // 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:$nav_version")
}
buildscript {
    repositories {
        google()
    }
    dependencies {
        val nav_version = "2.5.3"
        classpath("androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version")
    }
}
plugins {
    id("androidx.navigation.safeargs")
}

 

 

1. res -> navigation resource type으로 파일 생성

 

 

res / navigation / 설정한 파일명으로 생성되어있음 

 

 

2. 메인 프래그먼트, 이동할 프래그먼트들 생성 

 

별 다른건 없어요.. 저는 이동할 프래그먼트는 2개 생성할거라 아래와 같이 만들었습니다

못쉥겨도 이해해주세요 간단한 예제니까요

 

 

3.  메인 액티비티에 NavHostFragment 붙이기

여기선 싱글 액티비티로 사용할거기 때문에, 메인 액티비티에 NavHostFragment를 붙여줍니다

NavHost를 Activity에 붙여주는 작업이에요 ! 

✨ 처음 접하니까 여기서부터 정신차리지 않으면 뒤에서 헷갈리더라구여

 

<?xml version="1.0" encoding="utf-8"?>
<layout 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">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <androidx.fragment.app.FragmentContainerView
            android:id="@+id/fragmentContainerView"
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            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" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

하나씩 보자면

 

app:defaultNavHost = 여러 navHost 중 하나만 true를 사용할 수 있고, Back버튼을 가로챕니다 

app:navGraph = navigation 안에 어떤 파일을 쓸건지 명시

 

 

 

4.  nav_graph에서 화면 목적지 정하기 

 

 

+ 버튼으로 화면을 가져올 수 있고, 화면을 누르면 동그라면 저런 버튼이 나오는데, 저걸 끌면 화면에 연결할 수 있어요 :) 

 

 

 

5.  nav_graph 확인

저렇게 레이아웃을 끌어두면 아래와 같이 코드가 자동으로 생성됩니다 ! 

원래 action의 android:id가 아주 길게 생성되는데, 저는 그냥 제가 편한대로 네이밍했어요 

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

    <fragment
        android:id="@+id/mainFragment"
        android:name="kong.droid.jetpacknavi.MainFragment"
        android:label="MainFragment"
        tools:layout="@layout/main_fragment">
        <action
            android:id="@+id/toGrid"
            app:destination="@id/gridFragment" />
        <action
            android:id="@+id/toList"
            app:destination="@id/listFragment" />
    </fragment>
    <fragment
        android:id="@+id/gridFragment"
        android:name="kong.droid.jetpacknavi.GridFragment"
        android:label="GridFragment"
        tools:layout="@layout/fragment_grid" />
    <fragment
        android:id="@+id/listFragment"
        android:name="kong.droid.jetpacknavi.ListFragment"
        android:label="ListFragment"
        tools:layout="@layout/fragment_list" />
</navigation>

 

 


6.  mainActivity에서 navController 생성하기

여기서 꼭 navController를 명시해줘야합니다 

아니면 Fragment에서 navController를 가져와서 사용할 때 에러가 나더라구요 

lateinit var navController: NavController
    lateinit var binding : ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(LayoutInflater.from(this@MainActivity))
        setContentView(binding.root)

        navController = binding.fragmentContainerView.getFragment<NavHostFragment>().navController
    }

 

 

 

7.  mainFragment에서 이동 연결하기 

 

저는 데이터바인딩을 사용했기 때문에, 이렇게 선언해두고 xml에 연결시켰어요 

findNavController()시 Activity에서 navController가 뭔지 명시해두지 않으면 Exception 발생하니 주의하세요 

 

  fun moveToList(view: TextView) {
        val action =
            MainFragmentDirections
                .toList()
        view.findNavController().navigate(action)
    }

    fun moveToGrid(view: TextView) {
        val action =
            MainFragmentDirections
                .toGrid()
        view.findNavController().navigate(action)
    }

 


 

기본 이동만 붙이고, 애니메이션, args 전달은 아직 적용해보지 않았습니다 

2탄으로 돌아올게요

 

1탄의 소스는 아래에 있습니다 :)

 

https://github.com/eunie9498/JetpackExam

 

GitHub - eunie9498/JetpackExam: Jetpack Navigation Component

Jetpack Navigation Component . Contribute to eunie9498/JetpackExam development by creating an account on GitHub.

github.com

 

jetpack navigation 처음해보는데 싱글 액티비티 권장하는 요즘이니 익혀두면 좋을거같아요 

그리고 재밌네요 ㅎㅎ