[TIL] Navigation graph

박봉팔·2024년 1월 26일
0

Fragment화면간의 이동 및 흐름을 정의하기 위해 사용하는 구성요소이다.

Navigation graph를 사용하기 위해서는 크게 3가지가 필요하다.

1. NavGraph (네비게이션 그래프)

애플리케이션의 모든 네비게이션 관련 정보가 들어있는 XML리소스.
사용자가 앱 내에서 이동할수 있는 모든 Flow를 보여주며, 앱 내의 모든 Fragment를 한번에 확인할 수 있다.


2. NavHost (네비게이션 호스트)

앱에서 네비게이션 대상이 표시되는 빈 컨테이너로 사용자가 앱 사용중 화면을 전환할때 NavHost에 프래그먼트들이 교체되며 전환된다.

보통 FrameLayout이나 FragmentContainerView를 통해 구현되지만, 구글에서는 FragmentContanerView를 사용하길 권장하고 있다.


3. NavController

사용자가 화면을 전환할때 화면간의 이동과 네게이션 흐름을 관리해주는 역할을 해주는 객체이다.


사용방법

Navigation graph는 우선 Navigation graph xml파일을 설정해준 뒤, Fragment가 표시될 화면에 NavHost를 정의하고 소스코드에서 NavController를 연결해서 사용한다.


- Nav graph 정의

리소스 디렉토리 하위에 navigation디렉토리를 생성해준뒤, 원하는 이름으로 Navigation graph리소스 파일을 생성해준다.

<?xml version="1.0" encoding="utf-8"?>
<navigation
	...
    android:id="@+id/navi_graph"
    app:startDestination="@id/main">
    <!-- startDestination에 시작시 나올 Fragment의 Id를 넣어줘야한다. -->

    <fragment
        android:id="@+id/main"
        android:name="com.android.intensiveproject.fragment.MainFragment"
        android:label="main_fragment"
        tools:layout="@layout/fragment_main" />
        <!-- name에는 사용할 fragment의 경로를 넣어준다. -->

        ...
        
</navigation>

Nav graph에 사용할 Fragment들을 모두 정의해 준다.

만약 Bottom Navigation Menu와 연동하려면 menu파일에 있는 각 메뉴의 id값과
Nav graph내에 있는 Fragment중 해당 메뉴를 눌렀을때 실행될 Fragmentid가 같아야한다.

만약 두 id가 일치한다면 Bottom Navigation Bar의 메뉴와 해당 Fragment는 자동으로 연동되어 메뉴 클릭시 해당 Fragment로 이동이 가능하다.


  • Bottom navi menu
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <item
        android:id="@+id/main"
        android:enabled="true"
        android:icon="@drawable/btn_search_active"
        android:title="이미지 검색"
        app:showAsAction="always" />

    <item
        android:id="@+id/my_storage"
        android:enabled="true"
        android:icon="@drawable/btn_my_active"
        android:title="내 보관함"
        app:showAsAction="always" />

</menu>

  • Nav graph
<?xml version="1.0" encoding="utf-8"?>
<navigation ... >

    <fragment
        android:id="@+id/main"
        android:name="com.android.intensiveproject.fragment.MainFragment"
        android:label="main_fragment"
        tools:layout="@layout/fragment_main"/>

    <fragment
        android:id="@+id/search"
        android:name="com.android.intensiveproject.fragment.SearchFragment"
        android:label="search_fragment"
        tools:layout="@layout/fragment_search" />

</navigation>

- Nav Host 정의

Fragment를 표시할 ActivityNav Host를 생성해준다.

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host"
        android:name="androidx.navigation.fragment.NavHostFragment"  <-- NavHost받아옴
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:defaultNavHost="true"  <-- 기본 NavHost로 지정
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:navGraph="@navigation/navi_graph"  <-- NavGraph 연결
        tools:layout="@layout/fragment_main" />

- 소스 코드에서 Bottom Navigation 연결

리소스 파일이 준비가 끝나면 Fragment가 보여질 Activity의 소스코드에서 Nav HostNav Controller를 연결해준다.

val navHost = supportFragmentManager.findFragmentById(R.id.nav_host) as NavHostFragment

binding.bottomNavi.setupWithNavController(navHost.navController)

연결을 위해서는 현재 생성된 Fragment에 연동된 컨트롤러가 필요하기때문에 supportFragmentManagerfindFragmentByID를 사용해 생성되는 Nav host를 찾아온다.

Bottom NavigationsetupWithNavController를 사용해 Nav HostnavController를 연결해준다.


Fragment간 이동

Fragment간 이동을 위해서는 우선 Nav graph에서 Action을 생성해 줘야한다.

Nav graph의 디자인 탭에서 프래그먼트의 오른쪽에있는 점을 드래그하면 위와같이 화살표가 연결되는데, 이때 코드쪽으로 돌아오면 자동적으로 Action이 생성되어있는걸 확인할 수 있다.

해당 Action은 소스코드에서 이동을 하기위해 사용할 수 있다.

binding.button.setOnClickListener{
	findNavController().navigate(R.id.action_main_to_search)
}

위와 같이 findNavController를 통해 현재 사용되고있는 Nav Controller를 찾고, 이후 navigate메서드를 통해 실행시킬 Actionid를 입력해주면 해당 Action이 실행되며 화면이 전환된다.


오늘은 어땠나요?

진짜 이러다 죽을 수도 있지 않을까...?

진짜 적당히 해야할거같다.

profile
개발 첫걸음! 가보자구!

0개의 댓글