❓Navigation Component란???
- 안드로이드 Jetpack의 일부로, 앱 내에서 화면전환(네비게이션)을 관리하는데 도움을 주는 라이브러리!!
- 프래그먼트나 엑티비티 간의 이동, 인자(데이터)전달, 애니메이션, 앱바와의 통합을 간편하게 처리할 수 있도록 한다.
💻 구현하기
이제 직접 구현해보면서 알아보자.
먼저 build.gradle에 아래 코드들을 추가해준다
plugins {
id 'kotlin-kapt'
}
dependencies {
implementation("androidx.navigation:navigation-fragment-ktx:2.7.7")
implementation("androidx.navigation:navigation-ui-ktx:2.7.7")
}
build.gradle(Module)
그리고 Activity와 Fragment들을 생성해준다
1. Navigation Graph 생성
res 폴더 아래에 navigation 디렉터리를 만들고, nav_graph.xml 파일을 생성한다
Naviagtion Graph (XML파일)
- 앱의 모든 화면과 화면간의 이동경로(트랜지션)을 정의하는 XML파일
- 각 화면은 Fragment, Activity 또는 특정한 목적지를 나타냄
<?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/mapFragment">
<fragment
android:id="@+id/mapFragment"
android:name="nbc.group.recipes.presentation.fragment.MapFragment"
android:label="fragment_map"
tools:layout="@layout/fragment_map" />
<fragment
android:id="@+id/bookmarkFragment"
android:name="nbc.group.recipes.presentation.fragment.BookmarkFragment"
android:label="fragment_bookmark"
tools:layout="@layout/fragment_bookmark" />
</navigation>
nav_graph.xml
navigation
- app:startDestination="@+id/mapFragment" 속성을 추가한다
앱 실행 시 가장 처음 뜨는 프래그먼트를 지정하는 속성이다
fragment
- 프래그먼트들을 모두 정의해둔다
- name: 프래그먼트 파일의 경로를 넣어준다
- layout: 프래그먼트의 xml파일을 연결해준다
action으로는 화면 이동을 정의할 수 있음 (화면간의 연결)
굳이 코드를 작성해줄 필요없고 +폰아이콘을 누르면 선택할 수 있는 프래그먼트가 나와서 클릭하면 자동으로 코드가 짜여진다.
2. Menu 생성
res 폴더 아래에 menu 디렉터리를 만들고, nav_menu.xml 파일을 생성한다
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/mapFragment"
android:icon="@drawable/ic_home"
android:title="home"/>
<item
android:id="@+id/bookmarkFragment"
android:icon="@drawable/ic_bookmark"
android:title="bookmark"/>
</menu>
nav_menu.xml
주의할점!! -> id를 내비게이션 그래프의 프래그먼트 id와 동일하게 작성해야 맵핑을 통해 바텀내비게이션바로 만들어줄 수 있다.
- icon: 바텀내비게이션에 표시될 아이콘 이미지를 연결한다.
- title: 바텀내비게이션에 표시될 레이블 텍스트를 작성한다.
3. 클릭 시 색상지정
아이템을 클릭한 상태와 클릭하지 않은 상태에 색을 다르게 주기 위한 파일을 drawble에 생성해준다
android:state_checked="true"가 클릭한 상태, false가 클릭하지 않은 상태다
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 클릭했을 경우 -->
<item android:state_checked="true" android:color="@color/green1" />
<!-- 클릭하지 않은 경우 -->
<item android:state_checked="false" android:color="@color/black" />
</selector>
bottom_navigation_color.xml
# activtiy_main 레이아웃
<?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:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".presentation.MainActivity">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/fcv"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph"
app:layout_constraintBottom_toTopOf="@id/bottomNav_bar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottomNav_bar"
android:layout_width="match_parent"
android:layout_height="70dp"
app:itemIconTint="@drawable/bottom_navigation_color"
app:itemTextColor="@drawable/bottom_navigation_color"
app:labelVisibilityMode="labeled"
app:menu="@menu/menu"
app:itemActiveIndicatorStyle="@android:color/transparent"
app:itemBackground="@android:color/transparent"
android:background="@color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/fcv"/>
</androidx.constraintlayout.widget.ConstraintLayout>
activtiy_main.xml
- android:name="androidx.navigation.fragment.NavHostFragment"
- 탐색 그래프에서 대상을 표시하는 빈 컨테이너인 NavHost 역할을 하도록 설정한다
- NavHostFragment - 네비게이션 그래프를 관리하는 컨테이너로, 화면 전환의 중심역할! - app:navGraph="@navigation/nav_graph"
NavHostFragment와 내비게이션 그래프를 연결시킨다
- app:defaultNavHost="true"
뒤로가기 버튼을 누르면 NavHostFragment로 돌아오게 설정한것
기본값은 false이고, false로 설정할경우 뒤로가기 버튼을 누르면 앱이 종료된다
- BottomNavigationView
- app:labelVisibilityMode="labeled"
아이콘 밑의 레이블을 보이게 설정한다. 숨기고 싶으면 unlabeled로 설정한다.
- app:itemIconTint="@drawable/bottom_navigation_color"
app:itemTextColor="@drawable/bottom_navigation_color". 아이콘과 레이블의 색상을 지정해주는 속성인데, 아이템을 클릭한 상태와 클릭하지 않은 상태에 색을 다르게 주기 위해 위에서 만들었던 selector를 연결해준다.
- app:itemBackground="@android:color/transparent"
아이템을 클릭할 때 검은 원이 퍼져나가는 ripple효과를 제거하기 위한 속성이다.
# MainActivtiy
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var navController: NavController
...
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
initNavigation()
}
override fun onSupportNavigateUp(): Boolean {
navController = findNavController(R.id.fcv)
return navController.navigateUp() || super.onSupportNavigateUp()
}
private fun initNavigation() {
val navHostFragment = supportFragmentManager.findFragmentById(R.id.fcv) as NavHostFragment
val navController = navHostFragment.findNavController()
binding.bottomNavBar.setupWithNavController(navController)
}
}
MainActivtiy.kt
NavController
- 화면 전환을 제어하는 객체!
- 위에 작성한 레이아웃(NavHostFragment)와 연결되어, 화면 이동 및 상태를 관리!!!
이렇게하면 화면전환이 잘 구현된다.
4. Safe Args 사용해서 데이터 전달
참고로 Safe Args 사용해서 데이터 전달할수도 있다
(원래는 bundle로 데이터를 많이 전달했는데!!!! 이 방법이 더 유용하고 간단한 방법인듯하다)
- 이동하면서 action데이터를 바로 전달한다
val action = FirstFragmentDirections.actionFirstFragmentToSecondFragment("Sample Data")
findNavController().navigate(action) //이동하면서 action 데이터를 바로 전달함
데이터 수신하기
val args = SecondFragmentArgs.fromBundle(requireArguments())
val receivedData = args.someArgument
Safe Args 적용했을때 장점
⇒ Safe Args를 사용하면???
→ postId의 타입이 String임을 보장: 컴파일 타임에 확인되므로, 런타임 오류가 발생할 가능성이 줄어듬 (타입오류 방지가능)
→ Bundle 객체의 명시적 관리 필요 없음: 코드가 간결 + 데이터 전달 흐름을 더 명확히 볼 수 있음
그럼 Navigation Component를 적용하면 장점은??
간편한 네비게이션 관리
- 코드로 화면 전환을 직접할 필요 없이, 그래프를 통해 한눈에 구조파악 가능!
- Safe Args를 활용해, 데이터 전달시 타입오류 방지가능!
BackStack 자동 관리
- 네비게이션 컴포넌트가 BackStack(뒤로가기 스택)을 자동으로 관리해줌!! (스택이 쌓이지 않게 자동관리)
모듈화
- 각 화면이 독립적으로 설계되어, 유지보수 용이
UI 컴포넌트와 통합 용이
- ToolBar, BottomNavigationView, DrawerLayout 등과 쉽게 통합할 수 있음
📚참고자료
'Android > Jetpack' 카테고리의 다른 글
[Android/Kotlin] Paging3란? (2) | 2025.07.03 |
---|---|
[Android/Kotlin] Room의 3요소와 역할은 뭘까? (0) | 2024.06.23 |
[Android/Kotlin] 프래그먼트간 데이터를 공유하는 ViewModel (0) | 2024.06.05 |
[Android/Kotlin] Hilt란? (0) | 2024.05.24 |