Fragment화면간의 이동 및 흐름을 정의하기 위해 사용하는 구성요소이다.
Navigation graph
를 사용하기 위해서는 크게 3가지가 필요하다.
애플리케이션의 모든 네비게이션 관련 정보가 들어있는 XML
리소스.
사용자가 앱 내에서 이동할수 있는 모든 Flow
를 보여주며, 앱 내의 모든 Fragment
를 한번에 확인할 수 있다.
앱에서 네비게이션 대상이 표시되는 빈 컨테이너로 사용자가 앱 사용중 화면을 전환할때 NavHost
에 프래그먼트들이 교체되며 전환된다.
보통 FrameLayout
이나 FragmentContainerView
를 통해 구현되지만, 구글에서는 FragmentContanerView
를 사용하길 권장하고 있다.
사용자가 화면을 전환할때 화면간의 이동과 네게이션 흐름을 관리해주는 역할을 해주는 객체이다.
Navigation graph
는 우선 Navigation graph
xml파일을 설정해준 뒤, Fragment
가 표시될 화면에 NavHost
를 정의하고 소스코드에서 NavController
를 연결해서 사용한다.
리소스 디렉토리 하위에 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
중 해당 메뉴를 눌렀을때 실행될 Fragment
의 id
가 같아야한다.
만약 두 id
가 일치한다면 Bottom Navigation Bar
의 메뉴와 해당 Fragment
는 자동으로 연동되어 메뉴 클릭시 해당 Fragment
로 이동이 가능하다.
<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>
<?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>
Fragment
를 표시할 Activity
에 Nav 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" />
리소스 파일이 준비가 끝나면 Fragment
가 보여질 Activity
의 소스코드에서 Nav Host
에 Nav Controller
를 연결해준다.
val navHost = supportFragmentManager.findFragmentById(R.id.nav_host) as NavHostFragment
binding.bottomNavi.setupWithNavController(navHost.navController)
연결을 위해서는 현재 생성된 Fragment
에 연동된 컨트롤러가 필요하기때문에 supportFragmentManager
의 findFragmentByID
를 사용해 생성되는 Nav host
를 찾아온다.
Bottom Navigation
에 setupWithNavController
를 사용해 Nav Host
의 navController
를 연결해준다.
Fragment
간 이동을 위해서는 우선 Nav graph
에서 Action
을 생성해 줘야한다.
Nav graph
의 디자인 탭에서 프래그먼트의 오른쪽에있는 점을 드래그하면 위와같이 화살표가 연결되는데, 이때 코드쪽으로 돌아오면 자동적으로 Action
이 생성되어있는걸 확인할 수 있다.
해당 Action
은 소스코드에서 이동을 하기위해 사용할 수 있다.
binding.button.setOnClickListener{
findNavController().navigate(R.id.action_main_to_search)
}
위와 같이 findNavController
를 통해 현재 사용되고있는 Nav Controller
를 찾고, 이후 navigate
메서드를 통해 실행시킬 Action
의 id
를 입력해주면 해당 Action
이 실행되며 화면이 전환된다.
진짜 이러다 죽을 수도 있지 않을까...?
진짜 적당히 해야할거같다.