저번에 이어서 Navigation에 대한 정리를 해보겠습니다~!
이번 포스트에서는 아래와 같은 사항들에 대해서 알아보겠습니다.
- Nested graphs
- toolbar(app bar)
- bottom navigation
- back stack 관리
Nested graphs
Nested graphs란 쉽게 말해서 Navigation Graph 안에 또다른 graph를 연결해주는 것을 뜻합니다. 재사용이 많거나, 다른 그래프와 연결해주거나 할 때 유용하게 사용됩니다.
이러한 Nested graph를 사용하면 그래프들을 캡슐화할 수 있고, 간결하게 보여줄 수 있습니다.
돈을 송금하고, 계좌의 잔액을 확인하는 그래프가 아래와 같이 있다고 가정해봅니다!
여기서 송금할 이름 입력 (fillNameFragment) 와 보낼 금액 입력 (sendMoneyFragment) 프래그먼트가 다른곳에서 또 쓰이거나, 송금하기 라는 그래프로 묶고 싶은 경우 shift 키를 누르고 오른쪽 클릭 후에 Move to Nested Graph > New Graph 를 클릭하여 하나의 그래프로 묶습니다! 그렇게 되면, 아래와 같이 변경됩니다.
코드상에서는 <navigation 으로 시작하는 navigation graph가 한개 더 생성된 걸 볼 수 있습니다. 즉 그래프 안의 그래프이기 때문에 Nested Graph가 된것입니다~! 이는 동일하게 startDestination이 반드시 필요하고, 이동시에도 똑같이 해당 Nested Graph의 id를 주면, 이동하게 됩니다.
다만 이런식의 코드를 만들게 되면 Navigation의 코드가 너무 복잡해지게 됩니다. 아래와 같이요! (아래 사진에서 action의 id는 이전 1편에서 사용하던걸 계속 사용하다보니 이상한거니 크게 신경쓰지 마세요!!!)
이렇게 되면, 너무 복잡해진 코드로 인해 해당 코드들의 의도를 파악하기가 어려워집니다. 그래서 이러한 그래프를 따로 빼낸 뒤 include를 이용해 정리해낼 수 있습니다!
해당 중첩 navigation 코드를 다시 빼내어주고,
include 를 통해 해당 graph를 연결해줍니다.
여기서 app:graph는 navigation의 이름을, action을 통해 destination을 정해줄 땐, send_money_graph의 id를 넣어줘야합니다.
자! 이제 Nested Graph를 사용하면서도, 깔끔하게 관리가 가능해지면서도, Re Usable하고 캡슐화된 그래프 사용이 가능해졌습니다~ (아이 깔끔해)
Toolbar
규모가 있는 앱이라면 커스텀 툴바를 사용하겠지만, 여기서는 툴바의 기본 동작에 대해서만 알아봅니다.
Jetpack Navigation에는 NavigationUI라는 클래스가 포함되어 있는데, 이걸 사용해 상단에 앱바를 컨트롤 하거나, 바텀 네비게이션을 이용할 수도 있습니다.
NavigationUI는 Navigation Graph를 이용해 label을 가져와 앱바의 제목을 보여줄 수도 있습니다. 그러니 label도 적절하게 지정해주어야 합니다.
자 이제, Toolbar를 이용해 up 버튼을 활성화 하는 방법을 알아보겠습니다. 안드로이드에서 up 버튼은, toolbar에 있는 뒤로가기 버튼을 up 버튼이라고 합니다. 아래와 같은 버튼을요!
Toolbar
먼저 Activity의 xml에 Toolbar를 추가해줍니다.
그리고 onCreate()에서 다음과 같이 작성해줍니다.
이때 navController를 위와 같이 쓰지않으면 오류가 나는데, 오류가 나는 이유는 FragmentContainerView에서 NavController를 찾지 못하기 때문입니다. 그래서 NavController를 찾으려면 위와 같이 NavHostFragment에서 navController를 찾아야 합니다.
또한 추가로 위에 findViewById에서 Toolbar를 사용할 때 androidx, android 두개의 Toolbar가 있는데, android껄 import하면 setupWithNavController 메소드가 나오지 않으니 주의해야 합니다~!
위와같이 사용해주면 기본 Up 버튼은 활성화가 됩니다. 추가적으로 움직이는 toolbar인 CollapsingToolBarLayout은 https://velog.io/@bonimddal2/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-CollapsingToolbarLayout%EC%9C%BC%EB%A1%9C-%EC%9B%80%EC%A7%81%EC%9D%B4%EB%8A%94-%EC%83%81%EB%8B%A8%EB%B0%94-%EB%A7%8C%EB%93%A4%EA%B8%B0을 확인하시길 바랍니다.
혹시 up 버튼 동작에 커스텀하여 다른 작업을 하고싶다면, 아래의 가이드를 따라서 onSupportNavigateUp()을 수override하여 수정하면 됩니다.
Bottom Navigation
Jetpack Navigation을 이용해 Bottom Navigation도 사용할 수 있습니다.
먼저 xml에 BottomNavigationView를 작성해줍니다.
여기서 중요한건 id를 꼭 지정해주고, menu에 바텀 네비게이션에 들어갈 fragment들에 대해서 item들을 작성해줍니다.
id, icon title 세가지는 필수적으로 들어가야할 요소입니다. 이때 id가 꼭 navigation_graph와 일치해야만 이동합니다. 또한 추가적으로 Nested graph안의 id일 경우 작동하지 않고, 해당 Nested graph안에 있을 때만 작동합니다.
예를 들어 아래의 송금 Nested graph를 대입해서 생각해보면, firstFragment 상태일 때는 바텀 네비게이션이 작동하지 않고, sned_money로 이동했을 때에는 bottom_navigation이 작동합니다. (위의 메뉴 아이템의 item 2개가 send_money의 framgnet_id와 일치합니다)
또한 구글에서는 이러한 상황일 때, 2가지 방법을 제시했는데,
1. 도착 지점 id를 통해 toolbar와 Bottom Navigation의 visible을 처리해주는 방법
2. arguments를 적용해 true false 값으로 visible 처리하는 방법
default value와 argument를 가지고,
다음과 같이 appBar의 visible 처리를 해줍니다.
이는 BottomNavigationView가 있는 activity에서 해주면 됩니다.
Back Stack
Navigation을 이용해 Up 버튼을 클릭했을 때 뒤로가기 처리할 땐, findNavController().popBackStack() 을 이용해 뒤로 가기 처리를 하는 것이 국룰입니다. 하지만 기본적인 시스템의 백버튼은 stack 처럼 쌓인 프래그먼트들을 순차적으로 뒤로가게 해줍니다. 그런데, 바로 이전의 프래그먼트로 가는 것이 아닌 더 이전의 프래그먼트로 이동해야할 땐 어떻게 해야할까요?
몇가지 기능이 있는데, 가장 기본중 하나는 popUpTo 입니다. popUpTo를 이용해 A,B,C 프래그먼트가 있다고 가정할때, A->B->C 로 이동해서 C에 현재 있을 때, popUpTo="@+id/AFragment" 일 때, 프래그먼트 C와 B를 제거하고 A까지 이동합니다. 이때, popUpToInclusive 에 true를 주면 A까지 popUp 해버리고, false인 경우 A까지 돌아가게 됩니다.
구체적인 예를 들면, 이를 이용해 회원가입 완료 후 로그인을 했을 때, 뒤로가기 기능을 사용해도 다시 회원가입 로직을 타는 것이 아닌, 로그인 화면으로 되돌려 보낼 수 있도록 해주면, 더 나은 UX를 제공할 수 있게 됩니다.
외에도 NavOptions를 이용해 다양한 설정을 코드로 지정해줄 수도 있습니다.
다음 포스트 예고
view pager2 + tab layout
Sealed class와 이를 이용한 UI State
'Android' 카테고리의 다른 글
Android API 33대응! onBackPressed()는 deprecated 된다 (1) | 2022.10.23 |
---|---|
Sealed class + StateFlow (0) | 2022.10.09 |
Jetpack Navigation 총정리 1탄 (1) | 2022.09.19 |
Retrofit 파헤치기 (0) | 2022.09.15 |
Android 알람 만들기 (feat. Service, Broadcast Receiver) (0) | 2022.09.15 |