계속 업데이트 중.
참고
Jetpack Navigation Graph로 bottom navigation 설정하기
Jetpack Navigation Graph를 이용해 bottom navigation 만드는 방법
velog.io
https://developer.android.com/guide/navigation/navigation-ui
NavigationUI로 UI 구성요소 업데이트 | Android 개발자 | Android Developers
NavigationUI로 UI 구성요소 업데이트 탐색 구성요소에는 NavigationUI 클래스가 포함되어 있습니다. 이 클래스에는 상단 앱 바, 탐색 창 및 하단 탐색으로 탐색을 관리하는 정적 메서드가 포함되어 있
developer.android.com
Update UI Component With NavigationUI
우리는 UI Component(프래그먼트 및 액티비티)가 다른 UI Component로 이동할 때 유저들에게 더 친숙하고 유용한 탐색 방법을 제공할 필요가 있다. 이를 위해 NavigationUI를 사용할 수 있다.



네비게이션 Component는 NavigationUI Class를 포함한다. 해당 클래스는 위 이미지에서 보이는
"Top App Bar",
"Navigation Drawer",
"Bottom Navigation"
과 같은 네비게이션을, 관리할 수 있는 static method를 사용할 수 있다.
Tie Destination To Menu Item
NavigationUI class는 Navigation Drawer 또는 Bottom NavigationView 와 같이 Menu 와 Menu item을 필요로 하는 UI 와 목적지 UI를 연관시키는 helper method를 제공한다.
- onNavDestinationSelected()
MenuItem과 menu item과 연관된 목적지를 host하는 NavController를 매개변수로 필요로 하는 메서드.public static final boolean onNavDestinationSelected(MenuItem item, NavController navController)
MenuItem.onNavDestinationSelected(navController)
로 사용할 수도 있다.
해당 메서드가 호출되면, Menu Item의 id와 같은 id를 가진 목적지 UI로 아이템 클릭을 통해 이동할 수 있다.
(따라서 반드시 NavgiationUI가 포함하는 destination의 id와 Menu item의 id가 같아야지만 가능.)
//In Navigation.xml <?xml version="1.0" encoding="utf-8"?> <navigation xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" xmlns:android="http://schemas.android.com/apk/res/android" ... > ... <fragment android:id="@+id/details_page_fragment" android:label="@string/details" android:name="com.example.android.myapp.DetailsFragment" /> </navigation>
//In Menu.xml <menu xmlns:android="http://schemas.android.com/apk/res/android"> ... <item android:id="@+id/details_page_fragment" android:icon="@drawable/ic_details" android:title="@string/details" /> </menu>
Bottom Naviagtion
유저가 화면 하단에 위치한 메뉴 아이템을 선택할 때 NavController가 자동적으로 onNavDestinationSelected()를 호출하여 선택된 Item에 따라 UI를 자동적으로 업데이트 한다.
- main_activity.xml 파일에 bottom Navigation View 만들기.
<androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent"> <androidx.fragment.app.FragmentContainerView .../> <com.google.android.material.bottomnavigation.BottomNavigationView android:id="@+id/bot_naiv_menu" android:layout_width="0dp" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" app:labelVisibilityMode="labeled" app:menu="@menu/activity_main_bot_navi" /> </androidx.constraintlayout.widget.ConstraintLayout> - Bottom Navigation View의 menu와 연결해줄 activity_main_bot_navi.xml 만들기.
※ Menu item의 id는 navgiation.xml 파일 내 destination들의 id와 일치해야 한다.<menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/fragment_solaroid_gallery" android:icon="@drawable/gallery" android:enabled="true" android:title="갤러리"/> <item android:id="@+id/fragment_solaroid_frame" android:icon="@drawable/frame" android:enabled="true" android:title="액자식"/> </menu> - MainActivity class, onCreate() 메서드에서 navigationUI와 NavController를 연동해주기.
setupWithNavController(NavigationView, NavController) 메서드를 이용한다.
(NavigationView.setupWithNavController(NavController) 도 가능.)
val navHostFragment = binding.navHostFragment.getFragment<NavHostFragment>() //val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment val navController = navHostFragment.findNavController() binding.botNaivMenu.setupWithNavController(navController)
NavHostFragment 타입의 값 가져오는 방법.
① supprotFragmentManager.findFragmentById(R.id.~~) as NavHostFragment 사용.
//데이터 바인딩 시
② binding.~~~.getFragment<NavHostFragment>() 사용.
1~3과정을 거치면 menu item이 선택됐을 때 (Selected) onNavDestinationSelected()가 자동으로 호출되고 menu item의 id와 같은 destination을 찾아 이동한다. - BottomNavigation UI를 설정한 app의 모습


Listener for Navigation Events
우리는 NavigationView가 특정 Fragment로 이동했을 때만 보여지거나 안보여지길 원할 수 있다. 이러한 로직을 구현하기 위해서는 Navigation events listener를 이용해야 한다.
앞에서 보았듯이 NavController는 NavHost(Fragment)가 가진 내용물(current Destination : Fragments)을 새로운 내용물(other destination : Fragments) 로 교체하는 역할을 한다.
대부분의 경우, NavigationUI는 NavHost의 내용물에 포함되지 않는다. 따라서 NavController에 의해 UI가 다른 목적지로 이동할 때 NavigationUI는 별도로 로직을 구성해야만 한다.
NavController는 onDestinationChangedListener()를 제공하는데 이러한 리스너는 NavigationUI의 View상태를 바꾸거나 이벤트 설정을 해주고 싶을 때 유용하게 사용될 수 있다.
- onDestinationChangedListener(NavController, NavDestination, Bundle)
해당 리스너는 navController의 현재 도착지(current destination) 또는 navHost가 가진 argument가 바뀌면 호출된다.
새로운 메소드를 해당 리스너에 추가하고 싶다면, addOnDestinationChangedListener() 메서드를 사용한다. - addOnDestinationChagnedListener(onDestinationChangedListener)
해당 리스너와 람다식을 이용하여 다음과 같은 로직을 구현할 수 있다.
- 특정 fragment에서 NavigationUI 숨기기.
① destination id 사용.
//In MainActivity, onCreate() navController.addOnDestinationChangedListener{_,destination,_ -> if(destination.id == R.id.fragment_solaroid_create || destination.id == R.id.fragment_solaroid_detail) { binding.botNaivMenu.visibility = View.GONE } else { binding.botNaivMenu.visibility = View.VISIBLE } }
해당 코드는 navController가 이동하는 도착지의 id에 따라 NavigationUI의 visibility를 설정하는 방식이다.
② argument사용.
argument를 사용하는 방식은 navHost과 연결된 xml파일에 argument와 default값을 정의한 뒤 이를 이용하는 방식이다.
따라서 다음과 같이 <fragment> 내에 <argument>를 설정하는데, 이와 같은 argument는 네비게이션끼리 이동할 때 주고받을 수는 없다. (type이 명시되어 있지 않기 때문에?)<navigation xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/navigation" app:startDestination="@id/fragment_solaroid_gallery"> <fragment android:id="@+id/fragment_solaroid_gallery" android:name="com.example.solaroid.solaroidgallery.SolaroidGalleryFragment" android:label="SolaroidGalleryFragment" tools:layout="@layout/fragment_solaroid_gallery"> <argument android:name="ShowAppBar" android:defaultValue="true"/> </fragment> <fragment android:id="@+id/fragment_solaroid_frame" android:name="com.example.solaroid.solaroidframe.SolaroidFrameFragment" android:label="SolaroidFrameFragment" tools:layout="@layout/fragment_solaroid_frame"> <argument android:name="ShowAppBar" android:defaultValue="true"/> </fragment> </navigation>
//In MainActivity class, onCreate() navController.addOnDestinationChangedListener{_, _, argument -> binding.botNaivMenu.isVisible = argument?.getBoolean("ShowAppBar",false) == true }
-getBoolean(String, defalutValue) : 매개변수 String이 argument의 name이 맞는지 확인 후, 맞다면 true를 , 그렇지 않다면 defaultValue로 설정한 값 (해당 코드에서는 Boolean type의 false)을 반환. - 결과

