Study Record

[안드로이드] Navigation (탐색) 살펴보기 본문

안드로이드

[안드로이드] Navigation (탐색) 살펴보기

초코초코초코 2023. 6. 25. 22:56
728x90

😶 Navigation 개요

화면(Activity)전환을 할 때 항상 Activity 를 앱 내의 여러 콘텐츠를 탐색할 때(ex. 여러 fragment 를 탐색) 사용할 수 있는 Navigation Component가 있다.

 

Navigation 에는 NavigationGraph , NavHost, NavController를 구성요소로 가지고 있다.

 

Navigation Graph(탐색 그래프)

탐색 그래프는 앱 탐색의 가상 매핑정보가 있어 각 대상(Activity, Fragment 등)이 서로 관련되는 방식을 보여주는 XML 이다. 

 

NavHost

탐색 그래프에서 대상을 표시하는 빈 컨데이터로 NavHostFragment가 포함된다.

 

Nav Controller

NavController객체를 사용하면 NavHost에 표시되는 대상 간 탐색을 제어할 수 있다. 예를 들어, Activity내에서 NavController객체의 navigate() 메서드를 호출하여 Fragment를 교체할 수 있다.

 

 

😶 Navigation 활용하기

 

이 글에서 설명하는 예시는 한 Activity 에서 Fragment 간의 탐색 과정을 살펴본다.

 

 

기본 탐색의 과정은 StartFragment > workFragment > EndFirstFragment , EndSecondFragment > StartFragment 이다. 

 

 

탐색을 설정하기 전, Navigation 을 사용하기 위해 dependency 를 추가해 준다.

dependencies {
    implementation 'androidx.navigation:navigation-fragment-ktx:2.6.0'
    implementation 'androidx.navigation:navigation-ui-ktx:2.6.0'
}

 

 

 

1. dependency 추가 후 Navigation graph 파일을 만든다.

res/ 파일에 오른쪽 마우스 클릭 후 New > Android Resource Directory 생성 후 Resource type 을 navigation 으로 하고 이름을 Directory Name 을 navigation 인 디렉터리를 생성한다.

 

 

res/navigation/ 디렉터리에 새로운 파일 navigation.xml 을 생성한다. 이 파일은 Navigation graph 로써 기능한다. navigation.xml 파일을 수정하기 전, 탐색에 연결될 Fragment 들을 미리 생성한다.

 

 

2. Navgiation Graph 의 탐색을 추가한다.

 

2-1. fragment 추가하기

 

navigation.xml 파일에 splite 탭 혹은 design 탭을 누르면 위의 사진과 같은 부분을 누르면 연결을 추가할 Fragment 를 볼 수 있다. 사용할 Fragment 를 모두 클릭하면 자동으로 navigation.xml 파일에 fragment 가 추가된다.

<?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/navigation"
    app:startDestination="@id/startFragment"
    xmlns:tools="http://schemas.android.com/tools">

    <fragment
        android:id="@+id/startFragment"
        android:name="com.example.test2.StartFragment"
        android:label="StartFragment"
        tools:layout="@layout/fragment_start"/>
        
        ...
</navigation>

만약 프레그먼트를 추가했는데 미리 보기 화면이 나오지 않는다면 tools:layout 속성을 이용하여 해당 레이아웃에 연결해 준다. tools 로 시작하는 속성들은 실제 실행되는 앱에 영향을 미치지 않는다.

 

 

 

2-2. fragment 사이에 연결(탐색) 설정하기

예시에서는 startFragment > workFragment 로 이동한다. 여기서 ">" 이동한다는 표시를 <fragment> 태그에 <action> 태그를 이용하여 나타낼 수 있다.

 

 

코드로 직접 작성하기보단 splite 혹은 design 탭에서 fragment 를 클릭하면 좌우 양쪽에 동그란 원 모양을 클릭하여 연결될 fragment 에 끌어다 놓으면 <action> 이 완성된다.

 

 

 

코드로 보면 다음과 같다. <action> 태그의 app:detination 속성이 연결될 fragment 이고 나중에 id 로 action 들을 구분하여 프로그래밍으로 다음 fragment 로 이동하라고 명령할 수 있다.

<?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/navigation"
    app:startDestination="@id/startFragment"
    xmlns:tools="http://schemas.android.com/tools">

    <fragment
        android:id="@+id/startFragment"
        android:name="com.example.test2.StartFragment"
        android:label="StartFragment"
        tools:layout="@layout/fragment_start">
        <action
            android:id="@+id/action_startFragment_to_workFragment"
            app:destination="@id/workFragment" />
    </fragment>
</navigation>

 

 

 

2-3. Activity 에서 탐색 설정하기

 

Navigation 을 사용할 Acrivity 의 fragment 태그에 NavHostFragment 로 프래그먼트를 직접 적용해주고 app:navGraph 속성으로 Navigation graph(탐색이 설정된 xml 파일) 를 넣어준다. app:defaultNavHost 를 true 로 하면 기본적인 셋팅이 끝났다. defaultNavHost 값을 true 로 하면 프래그먼트 컨테이너가 탐색 계층 구조와 상호작용할 수 있다.

<androidx.fragment.app.FragmentContainerView
    android:id="@+id/main_fg"
    android:name="androidx.navigation.fragment.NavHostFragment"
    android:layout_width="0dp"
    android:layout_height="0dp"
    app:navGraph="@navigation/navigation"
    app:defaultNavHost="true"/>

 

 

 

😶 다음 Fragment 로 넘어가기

StartFragment > WorkFragment 로 넘어가는 <action> 을 미리 navigation.xml 에 추가했었다. 이제 이 연결정보를 이용해서 현재 StartFragment 에서 WorkFragment 로 넘어가는 방법은 NavController 를 사용하면 된다.

 

NavController 를 가져오는 방법은 다음 3가지 방법이 있다.

Fragment.findNavController()
View.findNavController()
Activity.findNavController(viewId: Int)

 

NavController 를 가져오면, navigate(resId: int) 함수에 인자로 미리 경로가 설정된 navigation.xml 파일의 <action> 의 id 를 설정하면 바로 다음 Fragment 로 넘어간다.

 

 

예를 들어 StartFragment 의 button 을 눌렀을 때 WorkFragment 로 넘어가는 흐름이라면 다음과 같다.

binding.workBtn.setOnClickListener {
    it.findNavController().navigate(R.id.action_startFragment_to_workFragment)
}

 

 

😶 Back Button 관리

 

안드로이드의 뒤로 가기 버튼을 눌렀을 때 Navigation 에서 관여할 수 있다. Fragment 의 이전 탐색 경로는 Back Stack 에 저장된다. 

 

 

만약, 탐색 경로(Back Stack) 이 startFragment > workFragment > endFirstFragment 의 순서로 쌓여있다면,  다시 startFragment 로 탐색(이동)할 경우 startFragment > workFragment > endFirstFragment > startFragment 가 될 것이다. 즉, 현재 Fragment 에서 startFragment 가 쌓인다. 이 상태(startFragment)에서 뒤로가기 버튼을 누르면 endFirstFragment 로 돌아갈 것이다.

 

하지만 startFragment > workFragment > endFirstFragment 에서 startFragment 로 탐색할 때 이전 경로에 있던 endFirstFragment 와 workFragment 를 종료하고 startFragment 로 돌아가고 싶을 때가 있다. 이럴 때 사용할 수 있는 게 app:popUpToapp:popUpToInclusive 속성이 있다.

 

app:popUpTo 는 특정 프래그먼트 id 값을 가질 수 있고 app:popUpToInclusive 는 true/false 값을 가질 수 있다. app:popUpTo="@id/startFragment" 라고 한다면 이전 탐색했던 경로 중 startFragment 가 있을 때까지 종료한다. 만약 app:popUpToInclusive 값이 true 라면 app:popUpTo 값의 startFragment 를 포함하여 종료하고 app:popUpToInclusive 갑이 false 이면 startFragment 를 남겨둔다.

 

현재 탐색 경로가 startFragment > workFragment > endFirstFragment 일 때 startFragment 로 다시 돌아가고 싶다면 app:destinaion="@id/startFragment",  app:popUpTo="@id/startFragment", app:popUpToInclusive="true" 로 설정하면 된다.

 

안드로이드에서 Design 탭의 탐색 경로 화살표를 클릭하고 Attributes 의 Pop Behavior 에서 간단하게 설정할 수 있다.

 

 

 

 

 

탐색  |  Android 개발자  |  Android Developers

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

developer.android.com

 

728x90