티스토리 뷰

728x90

 

Navigation

앱 내의 화면을 들어갔다 나올 수 있게 플로우를 정한다.

일반적으로 화면을 전환할 수 있는 하단바를 의미함.

 

 

Navigation 구성요소

  • Navigation Graph: 모든 Navigation 관련 정보가 한 곳에 모여있는 xml 파일. 사용자가 앱에서 갈 수 있는 모든 경로를 보여준다.
  • NavHost: Navigation Graph에서 화면을 표시하는 빈 컨테이너.
  • NavController: NavHost에서 앱 Navigation을 관리하는 객체. 사용자가 앱 내에서 화면을 이동할 때 NavHost에서 화면 전환을 controll하는 역할.

 

Navigation Graph에서 어떤 경로로 이동할지 NavController에게 전달하고, NavController는 NavHost에게 적절한 화면을 전달해준다. NavHost에서는 전달받은 화면을 띄운다.

 

 

Navigation 장점

  • 프래그먼트 트랜잭션 처리
  • '위로'와 '뒤로' 작업을 올바르게 처리
  • 화면 전환에 대한 애니메이션
  • 딥링크 구현 및 처리
  • Navigation UI 패턴들을 편리하게 추가
  • Safe Args - 화면 간 데이터를 전달할 때 type safety을 제공하는 Gradle plugin
  • ViewModel - Navigation Graph 에 대한 ViewModel을 확인해 화면 사이에 UI 관련 데이터를 공유

 

 

Navigation 시작하기

implementation("androidx.navigation:navigation-fragment-ktx:2.7.4")
implementation("androidx.navigation:navigation-ui-ktx:2.7.4")

module 수준의 builde.gradle에 위와 같은 의존성을 추가한다.

 

 

Navigation Graph 생성하기

  1. res 디렉터리 마우스 오른쪽 버튼, New > Android Resource File 선택
  2. File name 필드에 'nav_graph'와 같은 이름을 입력
  3. Resource type 드롭다운 목록에서 Navigation을 선택한 후 OK를 클릭

 

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

처음엔 아무 화면도 추가하지 않았기 때문에 위와 같은 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"
    app:startDestination="@+id/navigation_home">

    <fragment
        android:id="@+id/navigation_home"
        android:name="com.example.myapplication.ui.home.HomeFragment"
        android:label="@string/title_home"
        tools:layout="@layout/fragment_home" />

    <fragment
        android:id="@+id/navigation_dashboard"
        android:name="com.example.myapplication.ui.dashboard.DashboardFragment"
        android:label="@string/title_dashboard"
        tools:layout="@layout/fragment_dashboard" />

    <fragment
        android:id="@+id/navigation_notifications"
        android:name="com.example.myapplication.ui.notifications.NotificationsFragment"
        android:label="@string/title_notifications"
        tools:layout="@layout/fragment_notifications" />
</navigation>

navigation bar로 3개의 fragment를 전환하도록 하고 싶다면, 위와 같이 3개의 fragment를 추가한다.

이때 fragment의 xml 파일, kotlin 파일이 각각 존재해야 한다.

  • id: fragment를 구분할 아이디
  • name: fragment의 kotlin 파일 전체 경로
  • label: 화면의 이름 (navigation bar로 표시할 경우 이 label이 표시됨)
  • layout: fragment에 해당하는 xml

 

그리고 가장 루트의 <navigation> 태그 안에 startDestination 속성이 존재한다.

여기에는 nativation의 화면을 띄울 때 가장 먼저 보여야 할 fragment의 id를 넣어준다.

명시적으로 지정하지 않으면 오류가 발생한다.

 

 

Activity에 NavHost 추가

navigation을 띄울 Activity에 NavHost를 추가해보자.

NavHost는 사용자가 Navigation을 통해 화면을 전환할 때마다 빈 컨테이너를 통해 화면을 교체하는 역할을 한다.

 

 

<?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"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <fragment
        android:id="@+id/nav_host_fragment_activity_main"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:defaultNavHost="true"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:navGraph="@navigation/nav_graph" />
        
    <com.google.android.material.bottomnavigation.BottomNavigationView ... />

</androidx.constraintlayout.widget.ConstraintLayout>

navigation을 띄울 Activity에 위와 같은 fragment를 추가한다. (일반적으로 main Activity)

  • name: NavHost의 클래스 이름을 지정한다. 
  • navGraph: 아까 생성해두었던 Navigation Graph xml 파일명을 입력한다. NavHost를 Navigation Graph와 연결한다. 
  • defaultNavHost: true로 지정하면 NavHostFragment가 뒤로 가기 버튼의 액션을 가져간다 (뒤로 가기 버튼을 누르면 이전에 머물렀던 Navigation의 Fragment로 이동) 만약 NavHost가 여러개인 경우, 하나의 NavHost만 이 속성을 지정할 수 있다.

 

 

Navigation Bar 구현하기

지금까지는 Navigation Graph를 생성해서 Navigation 안에 어떤 Fragment가 포함될 것인지 지정하고,

NavHost를 생성해서 화면을 보여줄 빈 컨테이너를 생성했다.

이제 이 Fragment를 전환하기 위한 버튼이 포함된 Navigation Bar를 Activity에 추가해야 한다.

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:id="@+id/navigation_home"
        android:icon="@drawable/ic_home_black_24dp"
        android:title="@string/title_home" />

    <item
        android:id="@+id/navigation_dashboard"
        android:icon="@drawable/ic_dashboard_black_24dp"
        android:title="@string/title_dashboard" />

    <item
        android:id="@+id/navigation_notifications"
        android:icon="@drawable/ic_notifications_black_24dp"
        android:title="@string/title_notifications" />

</menu>

먼저 Navigation Bar에 들어갈 Fragment의 버튼들을 menu 형태로 생성한다.

bottom_nav_menu.xml라는 파일을 생성해서 Navigation Fragment 순서대로 item을 지정해주었다.

여기서 Activity에 보여질 icon과 title을 지정해준다.

 

<?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"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/nav_view"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:menu="@menu/bottom_nav_menu" />

    <fragment ... />

</androidx.constraintlayout.widget.ConstraintLayout>

NavHost를 지정해둔 동일한 Activity에 BottomNavigationView를 추가한다.

menu 속성에 방금 만들어둔 bottom_nav_menu를 지정한다.

 

이제 Navigation을 위한 ui 작업은 모두 끝났다.

마지막으로 Navigation을 띄울 Activity kotlin 파일에서 NavController를 연결하는 작업이 필요하다.

 

 

 NavController 연결하기

        val navView: BottomNavigationView = binding.navView

        val navController = findNavController(R.id.nav_host_fragment_activity_main)
        navView.setupWithNavController(navController)
  • Fragment.findNavController()
  • View.findNavController()
  • Activity.findNavController(viewId: Int)

NavController는 위와 같은 함수들을 통해 얻을 수 있다.

여기서 viewId는 xml 파일에서 NavHost View의 id가 된다.

 

그리고 Navigation Bar에 setupWithNavContoller()를 호출해서

NavController를 지정해주면 Navigation Bar에 대한 작업은 마무리된다.

 

 

+ Safe Args

Safe Args를 사용하여 Fragment 간에 Type Safe하게 데이터를 전달할 수 있다.

 

// module 수준
plugins {
    id("androidx.navigation.safeargs.kotlin")
}

// project 수준
buildscript {
    dependencies {
        classpath("androidx.navigation:navigation-safe-args-gradle-plugin:2.7.4")
    }
}

Safe Args를 사용하기 위해서는 module, project 수준의 build.gradle에 각각 의존성을 추가한다.

 

override fun onClick(view: View) {
    val action =
        SpecifyAmountFragmentDirections
            .actionSpecifyAmountFragmentToConfirmationFragment()
    view.findNavController().navigate(action)
}

Safe Args는 각 화면마다 navigate할 수 있는 클래스를 생성한다.

발신 대상이 SpecifyAmountFragment라고 할 때, 이 클래스의 이름은 SpecifyAmountFragmentDirections이 된다.

이 클래스는 navigate()의 인자로 전달할 수 있는 NavDirections 객체를 반환한다.

 

발신 대상이 SpecifyAmountFragment, 수신 대상이 ConfirmationFragment라고 할 때,

actionSpecifyAmountFragmentTo ConfirmationFragment()라는 메서드를 통해 발신 대상에서 수신 대상으로 이동할 수 있는 action을 반환한다.

 

 

마무리

Navigation Component를 사용하지 않고 Toolbar를 생성하듯이 menu로 Navigation을 생성해줄 수도 있다.

나한테는 그 방법이 더 익숙했는데, onItemSelected()를 각 Fragment마다 구현해주어야 하기 때문에 작성해야 할 코드가 훨씬 많아진다.

아직 Navigation Component의 action, Safe Args 등등.. 와닿지 않는 개념들이 있지만 여러번 학습해보면서 익혀가야겠다.

 

 

 

참고

https://developer.android.com/guide/navigation?hl=ko

https://developer.android.com/guide/navigation/navigation-getting-started?hl=ko

 

728x90
250x250
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
글 보관함