SW 공부노트

[안드로이드] Toolbar Custom with Navigation Components 본문

카테고리 없음

[안드로이드] Toolbar Custom with Navigation Components

요빈 2023. 8. 3. 14:14

https://developer.android.com/guide/navigation/navigation-ui?hl=ko 

 

NavigationUI로 UI 구성요소 업데이트  |  Android 개발자  |  Android Developers

NavigationUI로 UI 구성요소 업데이트 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 탐색 구성요소에는 NavigationUI 클래스가 포함되어 있습니다. 이 클래스에는

developer.android.com

Android Jetpack의 Navigation 기능을 적용한 커스텀 툴바를 구현하였다.

NavigationUI는 Toolbar, CollapsingToolbarLayout, Actionbar와 같은 상단 앱 바 유형을 지원한다.

이번 포스팅에서는 Toolbar를 사용할 예정이다.


0. 기본 설정

  • navigation 파일 (ex. nav_graph)
  • theme에서 NoActionBar 설정

1. 툴바 레이아웃 파일 생성

navigationIcon 속성은 기본 Toolbar에선 사용할 수 있지만 Navigation Components와 함께 사용하면 적용되지 않는다.

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <androidx.appcompat.widget.Toolbar
        android:id="@+id/main_tool_bar"
        android:layout_width="match_parent"
        android:layout_height="?android:actionBarSize"
        android:background="@color/white"/>
    <!--app:navigationIcon="@drawable/baseline_arrow"-->
</layout>

2. activity_main.xml 파일에 툴바 추가

<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
        
    <include
        android:id="@+id/main_toolbar"
        layout="@layout/toolbar"/>
        
    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="?actionBarSize"
        android:name="androidx.navigation.fragment.NavHostFragment"
        app:defaultNavHost="true"
        app:navGraph="@navigation/nav_graph"/>
</androidx.constraintlayout.widget.ConstraintLayout>

3. Activity 파일에서 툴바 관련 설정

  • setUpWithNavController() 호출 -> 커스텀 툴바에서 Navigation 기능 사용하기 위한 설정
  • AppBarConfiguration 객체에 탐색 그래프 전달
    • BottomNavigation과 같이 최상위 수준의 화면이 여러개이면 인수로 대상 ID 집합 전달

-> Up 버튼 기능만 구현하는 이번 포스팅에선 사용되지 않지만 메뉴 등 추가적인 기능 구현 시 사용될 수 있음

  • addOnDestinationChangedListener() -> 화면이 바뀔때마다 호출되는 메서드

툴바 레이아웃에 navigationIcon을 설정해둬도 Navigation Components에서 제공하는 디폴트 아이콘(<-)이 뜨는 문제가 있었다. 찾아보니 현재까지는 해당 아이콘을 커스텀할 수 있는 방법이 없다고 한다 😢

따라서 addOnDestinationChangedListener 메서드를 통해 따로 아이콘을 설정해주었다. 

자세한 내용은 아래 글을 참고하길 바란다.

https://stackoverflow.com/questions/62018283/how-to-change-toolbar-back-button-icon-in-android-material-components

class MainActivity : BaseActivity<ActivityMainBinding>(R.layout.activity_main) {

    private lateinit var navController: NavController
    private lateinit var appBarConfiguration: AppBarConfiguration

    // onCreate() 내부에서 호출
    override fun init() {
        val navHost = supportFragmentManager.findFragmentById(R.id.nav_host) as NavHost
        val toolbar = findViewById<Toolbar>(R.id.main_toolbar)
        navController = navHost.navController
        appBarConfiguration = AppBarConfiguration(navController.graph)
        toolbar.setupWithNavController(navController, appBarConfiguration)
        
        navController.addOnDestinationChangedListener { controller, destination, arguments ->
          if (destination.parent!!.startDestinationId != destination.id)
              toolbar.setNavigationIcon(R.drawable.baseline_arrow)
        }
    }
}

 

만약 toolbar를 통해 레이아웃 커스텀만 하고, 기존 Action Bar 기능은 그대로 사용하고 싶다면 setSupportActionBar를 통해 툴바 레이아웃 적용 후 Action Bar에서 Navigation Component 기능을 사용할 수 있도록 설정해주면 된다.

toolbar를 적용한 위 케이스와 달리 Action Bar를 적용하므로 setupActionBarWithNavContoller 메서드를 사용한다.

// onCreate() 내부에서 호출
override fun init() {
    val navHost = supportFragmentManager.findFragmentById(R.id.nav_host) as NavHost
    val toolbar = findViewById<Toolbar>(R.id.main_toolbar)
    navController = navHost.navController

    setSupportActionBar(toolbar)
    supportActionBar!!.setDisplayShowTitleEnabled(false) // 타이틀명 안보이게 지정

    appBarConfiguration = AppBarConfiguration(navController.graph)
    setupActionBarWithNavController(navController, appBarConfiguration)

    navController.addOnDestinationChangedListener { controller, destination, arguments ->
      if (destination.parent!!.startDestinationId != destination.id)
          toolbar.setNavigationIcon(R.drawable.baseline_arrow)
    }
}

// Up 버튼 기능
override fun onSupportNavigateUp(): Boolean {
    return super.onSupportNavigateUp() || navController.navigateUp(appBarConfiguration)
}

  • setSupportActionBar()에 Toolbar를 인수로 전달하면 Actionbar가 그 Toolbar의 완전한 소유권을 갖게 되므로 이 함수를 호출한 후에는 Toolbar API를 사용하면 안된다. -> ActionBar Support를 사용해 ActionBar를 NavController에 연결할 수 있다.
  • AppBarConfiguration 객체는 상단 바 관련 구성 옵션을 처리하는 객체
  • Toolbar를 사용할 때는 Navigation에서 탐색 버튼의 클릭 이벤트를 자동으로 처리하므로 onSupportNavigateUp() 재정의 X 
  • Toolbar + AppLayout을 통해 탭이 있는 상단 바 설정 가능 
  • Activity에서 호스팅하는 단일 상단 바 대신 프래그먼트마다 다른 상단 바를 사용하려면 프래그먼트의 onViewCreated() 메서드 내에서 setupWithNavController를 호출해야 한다.

 

Reference) 

https://chachas.tistory.com/17

 

[ Android ] Navigation

목차 시중에 나와있는 앱을 보면 복잡하게 이루어진 경우가 대부분으로 하나의 화면이나 두 개의 버튼으로 이루어진 화면처럼 간단하게 이루어진 앱을 찾아보기는 힘듭니다. Navigation은 화면을

chachas.tistory.com