기존의 Fragment
간의 이동을 구현할 때
supportFragmentManager.beginTransaction().
replace(R.id.frame_layout,GameFragment()).commit()
위와 같은 코드를 통해서 프래그먼트 간의 이동을 구현했습니다.
하지만 Android에서 Navigation이라는 컴포넌트를 통해서 간단하게 프래그먼트 끼리의 이동을 구현할 수 있습니다.
해당 내용은 공식문서를 통해서 공부했고, 그에 대한 제 생각을 적어봤습니다.
Navigation
공식문서에 따르면 Navigation의 정의는 아래와 같습니다.
Navigation은 Android 애플리케이션 내에서 '대상' 사이를 탐색하는 프레임워크로, 대상이 Fragment, Activity에 관계없이 일관된 API를 제공합니다.
탐색
이라는 말이 조금 모호한데, 탐색은 공식문서에서 다음과 같이 정의하고 있습니다.
사용자가 앱 내의 여러 콘텐츠를 탐색하고, 그곳에 들어갔다 나올 수 있게 하는 상호작용을 의미한다.
Android Studio에서 Navigation을 사용하려면 환경설정을 따로 해줘야 합니다.
해당 코드에서 navigation이 붙은 코드들을 모두 build.gradle(app)에 추가해줘야 합니다.
이렇게 gradle에 추가해 줬다면 프로젝트 내에서 navigation을 사용할 수 있습니다.
navigation을 사용하기 전의 Navigation Component
에 대해서 짚고 넘어가겠습니다.
Navigation Component는 크게 3가지로 구성됩니다.
- Navigation graph : 모든 탐색 관련 정보가 하나의 중심 위치에 모여있는 XML 리소스입니다.
- 탐색을 하는 흐름을 정의하는 xml 파일이라고 생각하면 됩니다.
- NavHost : 탐색 그래프에서 대상을 표시하는 빈 컨테이너입니다.
- 프래그먼트를 담는 화면이라고 생각하시면 됩니다.
- 기존에는 FrameLayout을 사용했는데, Navigation을 사용하려면 설정을 따로 해줘야 합니다
설정은 아래에 차차 설명하겠습니다.
- NavController : NavHost에서 앱 탐색을 관리하는 객체입니다.
전체적인 흐름은 다음과 같습니다.
Navgation Graph에서 어떠한 경로
로 이동할지 NavController에게 전달하고, NavController가 NavHost에 적절한 대상을 표시
하게 됩니다.
그럼 이제 각각의 구성요소에 대해서 뜯어보겠습니다.
Navigation Grpah
res 폴더에 navigation이라는 폴더를 만들어서 Navigation Graph를 만들어줍니다.
(꼭 폴더명이 navigation일 필요는 없지만 이렇게 네이밍 하는 것이 보편적이고, 알아보기 쉽다고 생각합니다!)
Navigation Grpah는 앱의 모든 탐색 경로를 나타낸다고 생각하시면 편합니다.
프래그먼트들 간의 탐색 흐름을 코드를 통해 작성할 수 있고, 시각적으로 보여주기도 합니다.
위 사진은 navgation.graph.xml의 디자인 탭을 누르면 보이는 화면입니다.
화살표를 통해서 어떠한 프래그먼트에서 어디로 도착하는지 명확하게 보여줍니다.
화살표의 추가는 프래그먼트에서 화살표를 디자인적으로 생성할 수 있고, 코드적으로도 생성할 수 있습니다.
디자인탭에서 ->를 클릭하면 action을 정의할 수 있습니다.
하지만 이러한 방법보다는 desin tab에서 프래그먼트를 클릭하고 화살표를 연결하는 방법이 조금 더 편한 거 같습니다.
아래는 이제 text 탭에서 코드적으로 action을 정의하는 방법입니다.
<fragment
android:id="@+id/OneFragment"
android:name="폴더경로"
android:label="fragment_one"
tools:layout="@layout/fragment_one"
<action
android:id="@+id/action_OneFragment_to_TwoFragment"
app:destination="@id/TwoFragment"
/>
<fragment
android:id="@+id/TwoFragment"
android:name="폴더경로"
android:label="fragment_two"
tools:layout="@layout/fragment_two"
/>
속성들은 다음과 같은 역할을 합니다.
- id : 코드에서 대상을 참조하는 데 사용되는 대상의 id
- name : 해당 프래그먼트가 위치한 경로를 "."형태로 표현합니다.
- 예를 들어 com.example.myApplcation.OneFragment가 될 겁니다.
- layout : 해당 프래그먼트의 xml 파일을 의미합니다.
- label : 사용자가 읽을 수 있는 대상 이름을 포함합니다.
- 공식문서에서는 리소스 문자열을 사용하는 것을 권장한다고 합니다.
- 이유는 NavGraph를 setupWithNavController()를 사용해 Toolbar에 연결할 경우 화면에 label 필드 값이 표시될 수도 있다고 합니다.
- 따라서 해당 프래그먼트가 어떠한 화면을 나타내는지를 string.xml에 추가하고 연결해 사용하면 됩니다
- 공식문서에서는 리소스 문자열을 사용하는 것을 권장한다고 합니다.
action
- id를 부여해 해당 action을 정의해서 적절한 이동을 구현할 수 있습니다.
- destination은 해당 액션의 행선지를 의미합니다.
NavHost
Navigtiaon Graph를 정의했다면 프래그먼트를 담을 NavHost
를 정의해야 합니다.
보통 하나의 액티비티에서 여러 프래그먼트를 연결하고, 이동을 구현하기에 액티비티 xml에 추가합니다.
속성은 다음과 같습니다.
- name : NavHost 클래스의 이름을 나타냅니다.
- navGraph : NavHostFragment와 연결된 Navication graph를 의미합니다.
- 여기서 추가적으로 defaultNavHost = true 속성을 사용하면 NavHostFragment가 뒤로 가기 버튼을 감지합니다.
- 백스택을 관리할 수 있습니다.
- 뒤로 가기 버튼을 누를 때마다 감지를 해서 백스택에서 화면을 팝 하고 이전 화면으로 돌아갈 수 있습니다.
- 백스택을 관리할 수 있습니다.
NavController
대상으로 이동하는 것은 NavController 객체를 통해서 실행됩니다.
NavController는 NavHost 내에서 앱 탐색
을 관리하고 있고, NavHost에는 자체 NavController가 있습니다.
아래와 같은 코드를 통해서 Navgation Controller를 검색할 수 있습니다.
navController = binding.navHostFragment.getFragment<NavHostFragment>().navController
아래와 같은 코드를 통해서 NavController를 사용해서 프래그먼트를 이동할 수 있습니다.
navController.navigate(actionId)
actionId는 Navigation Graph에서 정의한 actionId를 참조해서 넣어주면 됩니다.
보통 저는 BottomNavigation을 구현해서 Navigation을 이용합니다.
BottomNavigation을 사용하는 방법은 menu 폴더를 생성해서 xml을 생성합니다.
여기서 주의할 점은 menu에 정의된 item의 id값과 navigation_graph에 정의된 id값이 동일해야 프래그먼트가 연결됩니다.
Navigation Component와 같이 사용하기 위해서는 해당 id값을 동일해줘야 합니다.
그래야 정확하게 이동이 됩니다. 실제로 저도 id값을 아무렇게나 주다가 이동하지 않은 경험이 있었습니다..
binding.bottomNavigation.setupWithNavController(navController)
위 코드를 통해서 바텀내비게이션과 navController를 연결해서 사용하는 것입니다.
제가 생각하는 Navigation Component의 장점은 다음과 같습니다.
- 다양한 화면 전환을 관리할 수 있다.
- defaultNavHost = true라는 속성을 부여하면 백스택관리에 용이합니다.
- 구현이 간단하고, 흐름을 정의하는 것이 직관적이다.
참조
'Skils > Android' 카테고리의 다른 글
[Android] - 다국어 지원, String.xml 이용하기 (1) | 2023.10.19 |
---|---|
[Android] - DataBinding (0) | 2023.10.14 |
[Android] - Context (0) | 2023.02.22 |
[Android] - Live Data (0) | 2023.02.12 |
[Android] - ViewModel (0) | 2023.02.09 |