📱 안드로이드 Android ~ Kotlin

[Android/Kotiln] Jetpack Navigation 사용하기

핑크빛연어 2022. 5. 26. 18:35

 

안녕하세요! 이번 포스팅은 Jetpack Navigation 을 이용한 간단한 화면 이동을 구현해 보았습니당~

 

Jetpack Navigation

Jetpack 은 Android 개발을 빠르게 도와주는 컴포넌트 라이브러리입니다.
Jetpack Navigation 은 UI 를 통한 Navigation 편집이 가능하게 해주는 라이브러리로, 구글에서 권장하고 있는 네비게이션 중 하나입니다. 
단순한 버튼 클릭부터 좀 더 복잡한 패턴(앱바, 탐색 창)에 이르기까지 여러 가지 탐색을 구현하도록 도와줍니다. 
탐색 구성요소는 기존의 원칙을 준수하여 일관적이고 예측 가능한 사용자 환경을 보장합니다.

 

 🚨 Jetpack Navigation 의 3가지 주요 구성요소 

1. 탐색 그래프
           : 모든 탐색 관련 정보가 모여있는 xml 리소스. 이용가능한 경로가 포함되어있다.
2. NavHost
           : 탐색 그래프에서 대상을 표시하는 빈 컨테이너. 
             프래그먼트 대상을 표시하는 기본 NavHost 구현인 NavHostFragment  가 포함된다.
3. NavController
           : NavHost 에서 탐색을 관리하는 객체. 
     사용자가 앱 내에서 이동할 때 NavHost 에서 대상 콘텐츠를 전환하는 작업을 한다. 

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

 

탐색  |  Android 개발자  |  Android Developers

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

developer.android.com

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

 

 

💡 작성한 파일 목록 입니다.

1. build.gradle(:app)
2. res/navigation/nav_graph.xml
3. NavMainActivity.kt
4. res/layout/activity_nav_main.xml
5. OneFragment.kt (TwoFragment.kt, ThreeFragment.kt)
6. res/layout/fragment_one.xml (fragment_one)

 

1. build.gradle(:app)

viewBinding 을 사용하기 위해 viewBinding = true 를 추가하여 enable 할 수 있도록 하였고,
Jatpack Navigation 에 대한 의존성을 추가해줍니다.

plugins {
    id 'com.android.application'
    id 'kotlin-android'
}

android {
	...
    buildFeatures {
        viewBinding = true
    }
	...
}

dependencies {

	...
    
    // Jetpack Navigation
    implementation 'androidx.navigation:navigation-fragment-ktx:2.3.5'
    implementation 'androidx.navigation:navigation-ui-ktx:2.3.5'
    
	...
}

 

 

2. res/navigation/nav_graph.xml

res 경로에서 New > Directory 를 클릭하여 navigation 폴더를 생성하고,
nav_graph.xml 을 생성합니다. 

nav_graph.xml 는 Navigation 탐색 그래프 가 됩니다.
탐색 그래프를 통해 앱 내에서 사용자가 이용 가능한 모든 경로가 표시됩니다.

제가 작성한 코드는 OneFragment -> TwoFragment -> ThreeFragment -> OneFragment 순서로 순환하도록 Navigation 기능을 작성하였습니다.

app:startDestination="@id/fragmentOne" 는 navi 의 처음 시작점을 나타냅니다.

<fragment> 태그안에서 
어떤 프래그먼트를 사용하는지 명시해줍니다.(namelayout)
레이아웃을 매핑해서 디자인에서 화면을 확인할 수 있도록 합니다.
fragment 안에는 action, argument, deeplink 태그를 가질 수 있습니다.
action 은 화살표로 화면간의 이동을 나타내고, argument 는 데이터 전달 시 사용합니다.

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

    <fragment
        android:id="@+id/fragmentOne"
        android:name="com.eun.myappkotlin02.nav.OneFragment"
        android:label="fragment_one"
        tools:layout="@layout/fragment_one" >
        <action
            android:id="@+id/action_fragmentOne_to_fragmentTwo"
            app:destination="@id/fragmentTwo" />
    </fragment>

    <fragment
        android:id="@+id/fragmentTwo"
        android:name="com.eun.myappkotlin02.nav.TwoFragment"
        android:label="fragment_two"
        tools:layout="@layout/fragment_two" >
        <action
            android:id="@+id/action_fragmentTwo_to_fragmentThree"
            app:destination="@id/fragmentThree" />
    </fragment>

    <fragment
        android:id="@+id/fragmentThree"
        android:name="com.eun.myappkotlin02.nav.ThreeFragment"
        android:label="fragment_three"
        tools:layout="@layout/fragment_three" >
        <action
            android:id="@+id/action_fragmentThree_to_fragmentOne"
            app:destination="@id/fragmentOne" />
    </fragment>

</navigation>

 

 

3. NavMainActivity.kt

package com.eun.myappkotlin02.nav

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.eun.myappkotlin02.databinding.ActivityNavMainBinding

class NavMainActivity: AppCompatActivity() {

    companion object {
        const val TAG = "NaviMainActivity"
    }

    lateinit var binding: ActivityNavMainBinding
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityNavMainBinding.inflate(layoutInflater)
        setContentView(binding.root)  //setContentView(R.layout.activity_navi_main.xml)

    }

}

 

 

4. activity_nav_main.xml

NavMainActivity.kt 에 대한 레이아웃 리소스입니다.
activity_nav_main.xml 에 NavHost 에 대한 정의를 합니다.

<FragmentContainerView> 태그 안에

프래그먼트 대상을 표시하는 기본 NavHost 구현인 NavHostFragment 가 포함되도록 
android:name="androidx.navigation.fragment.NavHostFragment" 코드를 추가합니다.

app:defaultNavHost="true" 코드는 
시스템의 백버튼 등의 이벤트가 그래프와 연동이 되도록 합니다. 
true 로 설정하지 않을 경우 백버튼 시 앱이 종료됩니다.

app:navGraph="@navigation/nav_graph" 코드는 어떤 Navigation 탐색 그래프를 사용하는지 명시해줍니다.

Toolbar 은 어떤 fragment 에서든 표시되도록 추가하였습니다.

<?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=".nav.NavMainActivity">

    <Toolbar
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:background="@color/blue_light"
        android:elevation="5dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/naviHostFragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:defaultNavHost="true"
        app:navGraph="@navigation/nav_graph" />

</androidx.constraintlayout.widget.ConstraintLayout>

 

 

5. OneFragment.kt

NavController 를 통해 NavHost 에서 콘텐츠를 전환할 수 있도록 합니다.

OneFragment 의 NavController 는 Navigation.findNavController(binding.root).navigate(R.id.action_fragmentOne_to_fragmentTwo) 로,

TwoFragment 의 NavController 는 Navigation.findNavController(binding.root).navigate(R.id.action_fragmentTwo_to_fragmentThree) 로,

ThreeFragment 의 NavController 는 Navigation.findNavController(binding.root).navigate(R.id.action_fragmentThree_to_fragmentOne)

설정합니다.

TwoFragment.kt, ThreeFragment.kt 도 다음과 같습니다.

 

package com.eun.myappkotlin02.nav

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.navigation.Navigation
import com.eun.myappkotlin02.R
import com.eun.myappkotlin02.databinding.FragmentOneBinding

class OneFragment: Fragment() {

    private lateinit var binding: FragmentOneBinding

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
//        return super.onCreateView(inflater, container, savedInstanceState)

        binding = FragmentOneBinding.inflate(inflater, container, false)
        initView()
        return binding?.root
    }

    private fun initView() = with(binding) {
        binding.btnGo.setOnClickListener {
            Navigation.findNavController(binding.root).navigate(R.id.action_fragmentOne_to_fragmentTwo)
        }
    }

}

 

 

6. fragment_one.xml

OneFragment 에 대한 레이아웃 리소스입니다.
TwoFragment, ThreeFragment 에 대한 레이아웃 리소스 fragment_two.xml, fragment_three.xml 도 다음과 같습니다.

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

    <TextView
        android:id="@+id/tv_one"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="One"
        android:textAlignment="center"
        android:textSize="100sp"
        android:textStyle="bold"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/btn_go"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="30dp"
        android:text="go Two"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/tv_one" />

</androidx.constraintlayout.widget.ConstraintLayout>

 

 

결과 화면

One 화면에서 Go Two 버튼 클릭 시 Two 화면으로 이동,
Two 화면에서 Go Three 버튼 클릭 시 Three 화면으로 이동,
Three 화면에서 Go One 버튼 클릭 시 One 화면으로 이동합니다.

 

 

 

감사합니당 (✿◠‿◠)

 

728x90
반응형