안드로이드

[Android/Kotlin] 앱 바 App bar (3) NavigationUI와 App bar

란서 2022. 5. 23. 01:08

NavigationUI로 상단 앱 바 구성하기


NavigationUI 에는 사용자가 앱을 탐색할 때 상단 앱 바의 콘텐츠를 자동으로 업데이트 하는 메서드가 포함되어 있다.

예를 들어 NavigationUI는 탐색 그래프의 대상 라벨을 사용하여 상단 앱 바의 제목을 최신 상태로 유지한다.

 

<navigation>
    <fragment ...
              android:label="Page title">
      ...
    </fragment>
</navigation>

이처럼 <navigation> 태그 내에 있는 특정 <fragment> 의 label에 따라

 

상단 앱 바 타이틀

상단 앱 바의 title(제목)이 결정된다.

 

 

NavigationUI는 다음과 같은 상단 앱 바 유형을 지원한다.

 

  • Toolbar

  • ActionBar

  • CollapsingToolbarLayout

 

※ Toolbar를 setSupportActionBar()에 인수로 전달하면 ActionBar는 그 Toolbar의 전체 소유권을 가정한다.
따라서 해당 함수를 호출한 뒤에 Toolbar API를 사용하면 안된다. 

*ActionBar 지원를 사용하여 NavController에 연결이 가능. = NavigationUI와 연동.

 

AppBarConfiguration


NavigationUI는 AppBarConfiguration 객체를 사용하여 앱 표시 영역의 왼쪽 상단 모서리에 있는 탐색 버튼의 동작(≡)을 관리한다. 

탐색 버튼의 동작은 사용자가 최상위 수준 대상에 있는 여부에 따라 달라진다.

예를 들어 a프래그먼트는 최상위 수준 대상이고, b프래그먼트는 하위 대상일 때 a프래그먼트의 앱 바에는 위로 버튼(←)
을 표시하지 않으며, 오로지 하위 대상인 b프래그먼트에서만 위로 버튼을 표시한다.

만약 DrawerLayout을 사용중이라면 a프래그먼트에서는 (≡) 창 아이콘이 표시된다. 그렇지 않다면 탐색 버튼이 숨겨진다. 

 

 


시작 대상만 최상위 수준 대상으로 사용하여 탐색 버튼을 구성하려면 다음과 같이 AppBarConfiguration 객체를 만들어 해당하는 탐색 그래프에 전달한다.

val appBarConfiguration = AppBarConfiguration(navController.graph)


여러 최상위 수준 대상을 지정하여 탐색 버튼을 구성하는 경우도 있다. 이 경우 서로 계층적으로 관련이 없다.

따라서 다음과 같이 대상 ID 집합을 생성자에 대신 전달한다.

val appBarConfiguration = AppBarConfiguration(setOf(R.id.main, R.id.profile))



툴바 만들기


 

NavigationUI를 이용하여 Toolbar를 구성하는 경우 Toolbar를 정의한 뒤,
navController와 AppBarConfiguration 객체를 만들고 setupWithNavController()를 호출하여 인자로 넘긴다.

val toolbar = binding.toolbar

val navController = findNavController() or findNavController(R.id.nav_host_fragment)
val appBarConfiguration = AppBarConfiguration(navController.graph)

toolbar.setupWithNavController(navController, appBarConfiguration)

 

※ Toolbar를 사용할 때는 탐색에서 탐색 버튼의 클릭 이벤트를 자동으로 처리하므로
onSupportNavigateUp()을 재정의 할필요가 없다.


모든 대상에서 탐색 버튼이 위로 버튼으로 표시되려면 AppBarConfiguration을 빌드할 때,
topLevelDestinations 매개변수에 대해 empty 집합을 넣어주어야 한다. 

또한 setFallbackOnNavigateUpListener()를 사용하여 *navigateUp()이 그 외에 아무런 동작도 하지 않을 때의 대체 동작을 제어할 수 있다. (navigateUp() 메서드는 위로 가기 버튼을 실행시키는 함수)

val toolbar = binding.toolbar

val navController = findNavController() or findNavController(R.id.nav_host_fragment)
val appBarConfiguration = AppBarConfiguration(topLevelDestinationIds = setOf(), fallbackOnNavigateUpListener = ::onSupportNavigateUp)

toolbar.setupWithNavController(navController, appBarConfiguration)



CollapsingToolbarLayout


툴바로 CollapsingToolbarLayout을 포함하려면 먼저 아래와 같이 활동에 툴바와 주변 레이아웃을 정의.

 

    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="@dimen/tall_toolbar_height">

        <com.google.android.material.appbar.CollapsingToolbarLayout
            android:id="@+id/collapsing_toolbar_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:contentScrim="?attr/colorPrimary"
            app:expandedTitleGravity="top"
            app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">

            <androidx.appcompat.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:layout_collapseMode="pin"/>
        </com.google.android.material.appbar.CollapsingToolbarLayout>
    </com.google.android.material.appbar.AppBarLayout>

 

그런 다음, 아래와 같이 기본 활동의 onCreate 메서드에서 setupWithNavController() 를 호출한다.

val layout = binding.collapsingToolbarLayout
val toolbar = binding.toolbar
val navController = findNavController(R.id.nav_host_fragment) as NavHostFragment
val appBarConfiguration = AppBarConfiguration(navController.grah)
layout.setupWithNavController(toolbar, navController, appBarConfiguration)

 

toolbar가 아닌 다른 view (layout)에서 호출한 setupWithNavController()에는 Toolbar와 함께 NavController, AppBarConfiguration 객체를 넘겨주면 된다. 


작업 모음 ActionBar


기본 작업 모음(Action Bar)에 탐색 지원을 추가하려면 아래와 같이 기본 활동의 onCreate() 메서드에서 setupActionBarWithNavController()을 호출한다.
AppBarConfiguration은 onSupportNavigateUp()을 재정의할 때도 사용하므로 onCreate() 외부에 선언해야 한다.

private lateinit var appBarConfiguration: AppBarConfiguration

override fun oncreate() {
	val navController = findNavController(R.id.nav_host_fragment)
    appBarConfiguration = AppBarConfiguration(navController.graph)
    setupActionBarWithNavController(navController, appBarConfiguration)
}

onSupportNavigateUp()을 재정의하여 상단 탐색(≡)을 처리한다.

override fun onSupportNavigateUp() : Boolean {
	val navController = findNavController(R.id.nav_host_fragment)
    return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
}

※주의 : 해당 override 메서드가 없으면, 탐색 버튼을 누르더라도 drawerLayout이 나타나지 않는다.

 

탐색 창 추가 (NavigationView)


탐색 창은 앱의 기본 탐색 메뉴를 표시하는 UI 패널. 사용자가 앱 바에서 창 아이콘(≡) 을 터치하거나 화면의 왼쪽 가장자리에서 손가락을 스와이프하면 창이 표시된다.

 

탐색 창 (NavigationView)

창 아이콘(≡)은 DrawerLayout을 사용하는 모든 최상위 수준 대상에 표시된다.

탐색 창(navigationView)를 추가하려면 먼저 DrawerLayout을 루트 뷰로 선언하고,
DrawerLayout 내부에 기본  ui 콘텐츠와 탐색 창이 포함된 뷰를 추가하면 된다.

<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <!-- Layout to contain contents of main body of screen (drawer will slide over this) -->
    <androidx.fragment.app.FragmentContainerView
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:id="@+id/nav_host_fragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:defaultNavHost="true"
        app:navGraph="@navigation/nav_graph" />

    <!-- Container for contents of drawer - use NavigationView to make configuration easier -->
    <com.google.android.material.navigation.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true" />

</androidx.drawerlayout.widget.DrawerLayout>


다음과 같이 DrawerLayout을 AppBarConfiguration에 전달하여 탐색 그래프에 연결한다.

appBarConfiguration = AppBarConfiguration(navController.graph, binding.drawerLayout)
toolbar.setupWithNavController(navController,appBarConfiguration)
또는
setupActionBarWithNavController(navController, appBarConfiguration)