2021.06.16 - [Android/AAC, MVVM] - [Android] Navigation 라이브러리 사용과 Safe Arg 로 데이터 통신
Navigation 라이브러리를 사용하면 프래그먼트간의 이동을 쉽게 관리할 수 있다.
또한 자체적으로 프래그먼트 스택을 생성하여 백스택 관리를 용이하게 해 준다.
예시 네비게이션 구조는 위와 같다.
1️⃣ 일반적인 경우
위와 같이
BottomOne -> One -> Two -> One -> Two 로 이동하였을 경우 (시작점, 끝나는 지점)
스택이 쌓이게 되어
뒤로 가기 키를 누를 때마다
Two -> One -> Two -> One -> BottomOne
역순으로 잘 이동하는 것을 볼 수 있다.
findNavController().popBackStack()
또한 popBackStack을 활용하여 뒤로 가기 키를 누른 것과 동일한 동작을 할 수 있다.
app:popUpTo
액션에 popUpTo 속성으로 프래그먼트를 지정하면
그 액션 이후 뒤로 가기 버튼을 눌렀을 때 지정된 프래그먼트까지 이동하여 그 사이의 스택이 제거된다.
<fragment
android:id="@+id/oneFragment"
android:name="com.hanyeop.navigationex.OneFragment"
android:label="fragment_one"
tools:layout="@layout/fragment_one" >
<action
android:id="@+id/action_oneFragment_to_twoFragment"
app:destination="@id/twoFragment"
app:popUpTo="@id/bottomOneFragment"/>
<action
android:id="@+id/action_oneFragment_to_threeFragment"
app:destination="@id/threeFragment" />
위와 같이 One -> Two 액션에
popUpTo 로 bottomOne을 지정해주었다.
위와 같이
BottomOne -> One -> Two 로 이동한 상태에서
뒤로 가기 키를 누르면
Two -> BottomOne 으로 이동하는 것을 확인할 수 있다.
사이에 존재하던 One이 스택에서 제거되었다.
app:popUpToInclusive
popUpToInclusive 속성을 true로 설정해주면
스택에서 popUpTo로 지정된 프래그먼트도 제거한다.
<fragment
android:id="@+id/twoFragment"
android:name="com.hanyeop.navigationex.TwoFragment"
android:label="fragment_two"
tools:layout="@layout/fragment_two" >
<action
android:id="@+id/action_twoFragment_to_oneFragment"
app:destination="@id/oneFragment"
app:popUpTo="@id/oneFragment"
app:popUpToInclusive="true"/>
</fragment>
이번엔 Two -> One 액션에
popUpTo 로 One을 지정해주고,
popUpToInclusive 를 true로 지정해주었다.
BottomOne -> One -> Two -> One
순서에서 Two -> One 이동 때 스택에 저장되어 있는 One이 제거된다.
그래서 뒤로 가기 클릭 시
One -> BottomOne
로 이동하게 된다.
2️⃣ 바텀 네비게이션
바텀네비게이션의 경우는 스택이 별도로 쌓이지 않는다.
app:defaultNavHost="true" 속성이 지정되어 있는 경우
위와 같이 1 -> 2 -> 3 -> 2 -> 3 을 반복해도
뒤로 가기 한 번만 누르면 startDestination로 지정되어 있는 1로 이동하고 또 누르면 종료되는 것을 볼 수 있다.
app:defaultNavHost="false" 일 경우 한번만 뒤로 가기를 클릭해도 바로 종료된다.
만약 스택을 쌓고 싶다면 위처럼 바텀네비게이션 뷰의 아이템에
menuCategory를 전부 secondary로 설정해주면
역순으로 이동하는 것을 확인할 수 있다.
3️⃣ 특정 Fragment BackPress 처리
프래그먼트는 별도로 onBackPressed 가 존재하지 않기 때문에
프래그먼트를 가지고 있는 액티비티에서 처리해야한다.
navController의 currentDestination 속성을 활용하면
특정 화면에서의 BackPress 작업을 커스텀 할 수 있다.
var waitTime = 0L
override fun onBackPressed() {
if(navController.currentDestination?.id == R.id.bottomOneFragment) {
if (System.currentTimeMillis() - waitTime >= 1500) {
waitTime = System.currentTimeMillis()
Toast.makeText(this, "뒤로가기 버튼을 한번 더 누르면 종료됩니다.", Toast.LENGTH_SHORT).show()
} else {
finish() // 액티비티 종료
}
}
else{
super.onBackPressed()
}
}
위처럼 bottomOne 프래그먼트에서만 뒤로가기 2번 클릭 시 종료되는 기능을 구현할 수 있다.
https://github.com/HanYeop/AndroidStudio-Practice2/tree/master/NavigationEx