본문 바로가기

[Android]/허접 Programming Tips

[Navigation] Android Jetpack Navigation + BottomNavigationView (2 / 2)

안녕하세요 허접샴푸입니다!

 

Navigation 관련 2편입니다.

 

이번 편에서는 NavigationExtensions에 대해서 알아보고 MainActivity.kt 코드를 작성하도록 하겠습니다.

긴 말 없이 바로 이어나가도록 하겠습니다.

 

 

[START]

일단 먼저 1편에서도 말씀드렸지만, Google Sample을 참고한 것이기 때문에, 자세한 구현은 저도 모르는 부분들이 있습니다.

그러나 설명할 수 있는 부분까지 설명하도록 하겠습니다.

참고 : https://github.com/android/architecture-components-samples/tree/master/NavigationAdvancedSample

 

(1) NavigationExtensions.kt 복사 붙이기

https://github.com/android/architecture-components-samples/tree/master/NavigationAdvancedSample/app/src/main/java/com/example/android/navigationadvancedsample

위에 있는 NavigationExtensions.kt를 그대로 가져와 저희 프로젝트에 집어넣습니다. 해당 코드는 뒤에 알아보도록 하겠습니다.

음 Navigation을 사용해보신 분이라면, 현재 Back Stack 관련 문제가 제대로 해결되지 않았습니다. 물론 NavigationExtensions.kt를 커스터마이징하여 잘 쓰고 있는 똑똑한 분들도 있겠지만 Google에서 공식적으로 이것이 답이다! 하고 내놓은 버전은 아직 없습니다. 그래서 저 NavigationExtensions.kt에서도 "multiple back stack을 지원하기 전까진 이 샘플이 해결방법이다"라고 주석으로 적어 놓았습니다. 

그래서 저 또한 주저하지 않고 바로 이놈을 씁니다!

 

(2) MainActivity.kt 작성 (이 코드 또한 위 Google Sample Github의 MainActivity와 동일합니다.)

- onCreate에서 savedInstsanceState이 null이면 setUpBottomNavigationBar()을 합니다. savedInstanceState이 null이라는 뜻은 저장되어있는 번들 값이 없다는 뜻이며 앱이 처음 실행되었음을 의미합니다. 즉 처음 실행되었으니 바텀 내비게이션 바를 세팅해라는 뜻이네요.

- onRestoreInstanceState은 onStart() 다음에 호출되는 override 함수입니다. 화면이 회전되게 되면 해당 Activity는 onCreate부터 다시 생명주기 함수들을 호출합니다. 이때 savedInstanceState은 null이 아니게 되며, onRestoreInstanceState이 호출되게 됩니다. 

- onRestoreInstanceState이 되면 기존에 있었던 BottomNavigationView의 instance state과 selectedItemId가 복구되어 setupBottomNavigationBar()을 다시 호출하여 selectedItemId에 맞는 fragment를 화면에 보여주게 됩니다.

(관련 내용은 아래 그림 참조)

출처: https://stackoverflow.com/questions/4853505/android-how-to-disable-feature-no-title/4853734#4853734

- setupWithNavController을 통해 bottomNavigationView를 앞 1편에서 만든 Navigation graph들과 연결시켜줍니다.

- setupActionBarWithNavController는 현재 보이고 있는 Fragment의 title을 actionbar에 표시해주거나, 뒤로 가기 버튼 등 Navigatino Controller와  Actionbar을 자동적으로 이어줍니다. Observer을 붙여서, navigationController에 변화가 있을 때마다 ActionBar을 설정하도록 해줍니다.

 

- onSupportNavigateUp은 Actionbar에서 뒤로 가기 버튼을 눌렀을 때 호출되며, 뒤로 갈 수 있으면 navigateUp() boolean 값을 반환하며 true일 것이며, 뒤로 갈 수 없으면 null일 것이며 false를 반환합니다.

 

(결과 화면)

 

여기서 잠깐!

위 결과 화면에서 Home 화면을 보면, "NAVIGATE TO HOME DETAIL FRAGMENT" 버튼이 보이시죠?

네 맞습니다. 해당 버튼을 누르면 detail fragment로 navigate 하는 방법을 알려드리겠습니다.

 

(1) 먼저 HomeDetailFragment와 fragment_home_detail.xml 파일을 생성합니다.

 

(2) res > navigation > navigation_home.xml으로 가서 위에서 만든 fragment를 추가합니다.

 

(3) 아래와 같이 HomeFragment에서 HomeDetailFragment로 화살표를 이어줍니다.

화살표를 이으면, 오른쪽에 "id"에 "action_homeFragment_to_homeDetailFragment"라고 적혀 있는 것을 확인할 수 있습니다. id는 자신이 원하는 형태로 바꾸어도 되며 꼭 저 형식일 필요는 없습니다.

예로, action_navigate 이런 식으로 바꾸어도 무방합니다.

 

(4) HomeFragment.kt 버튼 클릭 리스너 추가 및 navigate!

- navigate_to_home_detail_button에 clickListener을 달아 줍니다.

- 위에서 말한 "id"를 여기서 이제 사용하면 끝입니다! 

findNavController().navigate(R.id.action_homeFragment_to_homeDetailFragment)

- findNavController()은 현재 Fragment의 NavController을 찾으며, navigate은 navigation graph에서 해당 id의 action을 찾아 그 action의 목적지로 navigate 해줍니다. 

 

(결과 화면)

 

 

[Github]

https://github.com/DJDrama/Playground/tree/master/TestNavigation

 

DJDrama/Playground

Contribute to DJDrama/Playground development by creating an account on GitHub.

github.com

 

이렇게 2편에 걸쳐서 Android Navigation, BottomNavigationView에 대해서 아주 약하게 맛만 보았습니다.

맛을 본 이유는 무엇일까요?

배달의 민족 App이 BottomNavigationView로 이루어져 있기 때문에 따라 만들기 위해서 잠시 짬을 내어 이렇게 작성해보았습니다.

그럼 배달의 민족 App 따라 만들 때 더 자세히 다루어보도록 하겠습니다. 뿅~!