Navigation은 Jetpack 라이브러리중 하나로 Fragment 간의 흐름을 설정할 수 있고, 눈으로도 바로 확인할 수 있기 때문에 유용하게 사용할 수 있습니다.
Navigation 은 아래 3개의 구성 요소로 이루어져있습니다.
Navigation Graph : 모든 Navigation 관련 정보가 하나의 중심 위치에 모여있는 XML 리소스 파일입니다. destination 이라고 부르는 앱 내의 모든 개별적 콘텐츠 영역과 사용자가 앱에서 갈 수 있는 모든 경로가 포함됩니다.
NavHost : Navigation Graph 에서 대상을 표시하는 빈 컨테이너 입니다. 대상 구성요소에는 프래그먼트 대상을 표시하는 기본 NavHost 의 구현인 NavHostFragment가 포함됩니다.
NavController : NavHost 에서 Navigation 을 관리하는 객체입니다. NavController 를 통해 콘텐츠를 전환할 수 있습니다.
Jetpack의 Navigation을 사용하기 위해서는, 먼저 app 레벨의 build.gradle에 의존성을 추가해줍니다.
dependencies {
...
// Navigation JetPack
implementation "androidx.navigation:navigation-fragment-ktx:2.5.0"
implementation "androidx.navigation:navigation-ui-ktx:2.5.0"
...
}
만약 Navigation 에서 제공하는 Safe Args 를 통해 대상 간 데이터를 전달하고 싶으면, 프로젝트 레벨의 build.gradle에 해당 classpath를 추가합니다.
buildscript {
repositories {
google()
}
dependencies {
def nav_version = "2.5.0"
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
}
}
그리고 app 레벨의 build.gradle 에도 Safe Args 의존성을 추가합니다.
plugins {
id 'androidx.navigation.safeargs'
}
resource directory 를 만들어 줍니다.

Fragment 간의 연결 관계를 설정해줍니다. 직전에 생성한 main_van_graph.xml 파일에 연결 할 Fragment를 추가해줍시다.Fragment 를 추가해줍니다.
Fragment 를 확인할 수 있습니다.Fragment 간의 연결 관계를 설정하기 위해 시작 Fragment 의 오른쪽 동그라미를 도착 Fragment 에 끌어서 연결해줍니다.
Fragment 간의 연결 관계가 설정됩니다.main_nav_garph.xml 파일의 코드를 확인하면 action 태그가 추가된 것을 확인할 수 있습니다.
Fragment 를 담을 Container 를 만들어줍니다.Container 에 다른 Fragment 가 올라오면서 화면이 전환됩니다.androidx.fragment.app.FragmentContainerView 태그로 컨테이너를 만들 수 있습니다.activty_main.xml
<?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">
<data>
<variable
name="activity"
type="com.jae464.placememo.MainActivity" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintBottom_toTopOf="@id/bottomNavigationView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/main_nav_graph" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottomNavigationView"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/nav_host_fragment"
app:menu="@menu/bottom_navigation_menu" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
android:name="androidx.navigation.fragment.NavHostFragment" 로 이름을 지정해줍니다.app:navGraph 속성에 전에 만들었던 navigation 리소스 파일 을 넣어줍니다.app:defaultNavHost="true" 를 지정하면, NavHostFragment 가 시스템 뒤로 가기 버튼을 가로챕니다. 하나의 NavHost 만 기본값으로 지정할 수 있습니다.NavController 를 통해 Navigation 을 조작할 수 있습니다.NavController 를 가져옵니다.@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var navController: NavController
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
binding.activity = this
// NavController 가져오기
val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
navController = navHostFragment.findNavController()
}
}
HomeFragment 에서 업로드 버튼을 누르면 PostFragment로 이동하도록 해봅시다.@AndroidEntryPoint
class HomeFragment : BaseFragment<FragmentHomeBinding>(R.layout.fragment_home) {
private val viewModel: HomeViewModel by viewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.postButton.setOnClickListener {
findNavController().navigate(
R.id.action_home_to_post
)
}
}
}
navigation graph 를 만들 때 지정했던 action 을 navigate() 안의 인자로 넣어주면, 화면을 전환할 수 있습니다.setUpWithNavController 메서드를 사용하면 쉽게 BottomNavigationView 와 AppBar 를 연결할 수 있습니다.
BottomNavigationView에 관한 글은 아래 글을 참조해주시기 바랍니다.
https://velog.io/@jae464/Android-Bottom-Navigation-View-%EB%A7%8C%EB%93%A4%EA%B8%B0
그럼 실제 코드를 통해 알아보겠습니다.
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var navController: NavController
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
binding.activity = this
initNavigation()
}
private fun initNavigation() {
val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
navController = navHostFragment.findNavController()
binding.bottomNavigationView.setupWithNavController(navController)
}
}