적응형 탐색 빌드

대부분의 앱에는 앱의 기본 탐색 UI를 통해 액세스할 수 있는 몇 가지 최상위 대상이 있습니다. 표준 휴대전화 디스플레이와 같은 소형 창에서는 일반적으로 대상이 창 하단의 탐색 메뉴에 표시됩니다. 태블릿의 전체 화면 앱과 같이 확장된 창에서는 기기의 왼쪽과 오른쪽을 잡고 있으면 탐색 컨트롤에 더 쉽게 도달할 수 있으므로 앱 옆에 있는 탐색 레일이 일반적으로 더 좋습니다.

NavigationSuiteScaffoldWindowSizeClass를 기반으로 적절한 탐색 UI 컴포저블을 표시하여 탐색 UI 간에 전환하는 것을 간소화합니다. 여기에는 런타임 창 크기 변경 중에 UI를 동적으로 변경하는 것이 포함됩니다. 기본 동작은 다음 UI 구성요소 중 하나를 표시하는 것입니다.

  • 너비 또는 높이가 작거나 기기가 테이블탑 모드인 경우 탐색 메뉴
  • 그 외의 모든 항목에는 탐색 레일을 사용합니다.
그림 1. NavigationSuiteScaffold: 소형 창에 탐색 메뉴를 표시합니다.
그림 2. NavigationSuiteScaffold: 펼쳐진 창에 탐색 레일을 표시합니다.

종속 항목 추가

NavigationSuiteScaffoldMaterial3 적응형 탐색 모음 라이브러리의 일부입니다. 앱 또는 모듈의 build.gradle 파일에 라이브러리의 종속 항목을 추가합니다.

Kotlin

implementation("androidx.compose.material3:material3-adaptive-navigation-suite")

Groovy

implementation 'androidx.compose.material3:material3-adaptive-navigation-suite'

스케폴드 만들기

NavigationSuiteScaffold의 두 가지 주요 부분은 탐색 모음 항목과 선택한 대상의 콘텐츠입니다. 컴포저블에서 탐색 모음 항목을 직접 정의할 수 있지만, enum과 같이 다른 곳에서 정의하는 것이 일반적입니다.

enum class AppDestinations(
    @StringRes val label: Int,
    val icon: ImageVector,
    @StringRes val contentDescription: Int
) {
    HOME(R.string.home, Icons.Default.Home, R.string.home),
    FAVORITES(R.string.favorites, Icons.Default.Favorite, R.string.favorites),
    SHOPPING(R.string.shopping, Icons.Default.ShoppingCart, R.string.shopping),
    PROFILE(R.string.profile, Icons.Default.AccountBox, R.string.profile),
}

NavigationSuiteScaffold를 사용하려면 현재 대상을 추적해야 하며, 이는 rememberSaveable를 사용하여 할 수 있습니다.

var currentDestination by rememberSaveable { mutableStateOf(AppDestinations.HOME) }

다음 예에서 navigationSuiteItems 매개변수 (유형 NavigationSuiteScope)는 item 함수를 사용하여 개별 대상의 탐색 UI를 정의합니다. 대상 UI는 탐색 메뉴, 레일, 창 전반에서 사용됩니다. 탐색 항목을 만들려면 AppDestinations (이전 스니펫에 정의됨)를 반복합니다.

NavigationSuiteScaffold(
    navigationSuiteItems = {
        AppDestinations.entries.forEach {
            item(
                icon = {
                    Icon(
                        it.icon,
                        contentDescription = stringResource(it.contentDescription)
                    )
                },
                label = { Text(stringResource(it.label)) },
                selected = it == currentDestination,
                onClick = { currentDestination = it }
            )
        }
    }
) {
    // TODO: Destination content.
}

대상 콘텐츠 람다 내에서 currentDestination 값을 사용하여 표시할 UI를 결정합니다. 앱에서 탐색 라이브러리를 사용하는 경우 여기에서 적절한 대상을 표시하는 데 사용합니다. when 문이면 충분합니다.

NavigationSuiteScaffold(
    navigationSuiteItems = { /*...*/ }
) {
    // Destination content.
    when (currentDestination) {
        AppDestinations.HOME -> HomeDestination()
        AppDestinations.FAVORITES -> FavoritesDestination()
        AppDestinations.SHOPPING -> ShoppingDestination()
        AppDestinations.PROFILE -> ProfileDestination()
    }
}

색상 변경

NavigationSuiteScaffold는 스캐폴드가 차지하는 전체 영역(일반적으로 전체 창)에 Surface를 만듭니다. 또한 스캐폴드는 NavigationBar와 같은 특정 탐색 UI를 그립니다. 노출 영역과 탐색 UI는 모두 앱 테마에 지정된 값을 사용하지만 테마 값을 재정의할 수 있습니다.

containerColor 매개변수는 노출 영역의 색상을 지정합니다. 기본값은 색 구성표의 배경 색상입니다. contentColor 매개변수는 해당 노출 영역 콘텐츠 색상을 지정합니다. 기본값은 containerColor에 지정된 항목의 '사용' 색상입니다. 예를 들어 containerColorbackground 색상을 사용하는 경우 contentColoronBackground 색상을 사용합니다. 색상 시스템의 작동 방식에 관한 자세한 내용은 Compose의 Material Design 3 테마 설정을 참고하세요. 이러한 값을 재정의할 때는 앱이 어두운 디스플레이 모드와 밝은 디스플레이 모드를 지원하도록 테마에 정의된 값을 사용하세요.

NavigationSuiteScaffold(
    navigationSuiteItems = { /* ... */ },
    containerColor = MaterialTheme.colorScheme.primary,
    contentColor = MaterialTheme.colorScheme.onPrimary,
) {
    // Content...
}

탐색 UI가 NavigationSuiteScaffold 노출 영역 앞에 그려집니다. UI 색상의 기본값은 NavigationSuiteDefaults.colors()에서 제공하지만 이러한 값도 재정의할 수 있습니다. 예를 들어 탐색 메뉴의 배경을 투명하게 하고 다른 값은 기본값으로 하려면 navigationBarContainerColor를 재정의합니다.

NavigationSuiteScaffold(
    navigationSuiteItems = { /* ... */ },
    navigationSuiteColors = NavigationSuiteDefaults.colors(
        navigationBarContainerColor = Color.Transparent,
    )
) {
    // Content...
}

궁극적으로 탐색 UI에서 각 항목을 맞춤설정할 수 있습니다. item 함수를 호출할 때 NavigationSuiteItemColors의 인스턴스를 전달할 수 있습니다. 이 클래스는 탐색 메뉴, 탐색 레일, 탐색 창의 항목 색상을 지정합니다. 즉, 각 탐색 UI 유형에서 동일한 색상을 사용하거나 필요에 따라 색상을 다르게 지정할 수 있습니다. 모든 항목에 동일한 객체 인스턴스를 사용하도록 NavigationSuiteScaffold 수준에서 색상을 정의하고 NavigationSuiteDefaults.itemColors() 함수를 호출하여 변경하려는 색상만 재정의합니다.

val myNavigationSuiteItemColors = NavigationSuiteDefaults.itemColors(
    navigationBarItemColors = NavigationBarItemDefaults.colors(
        indicatorColor = MaterialTheme.colorScheme.primaryContainer,
        selectedIconColor = MaterialTheme.colorScheme.onPrimaryContainer
    ),
)

NavigationSuiteScaffold(
    navigationSuiteItems = {
        AppDestinations.entries.forEach {
            item(
                icon = {
                    Icon(
                        it.icon,
                        contentDescription = stringResource(it.contentDescription)
                    )
                },
                label = { Text(stringResource(it.label)) },
                selected = it == currentDestination,
                onClick = { currentDestination = it },
                colors = myNavigationSuiteItemColors,
            )
        }
    },
) {
    // Content...
}

탐색 유형 맞춤설정

NavigationSuiteScaffold의 기본 동작은 창 크기 클래스에 따라 탐색 UI를 변경합니다. 하지만 이 동작을 재정의하는 것이 좋습니다. 예를 들어 앱이 피드의 콘텐츠가 포함된 하나의 큰 창을 표시하는 경우 앱은 확장된 창에 영구 탐색 창을 사용하지만 소형 및 중형 창 크기 클래스의 경우 기본 동작으로 대체할 수 있습니다.

val adaptiveInfo = currentWindowAdaptiveInfo()
val customNavSuiteType = with(adaptiveInfo) {
    if (windowSizeClass.windowWidthSizeClass == WindowWidthSizeClass.EXPANDED) {
        NavigationSuiteType.NavigationDrawer
    } else {
        NavigationSuiteScaffoldDefaults.calculateFromAdaptiveInfo(adaptiveInfo)
    }
}

NavigationSuiteScaffold(
    navigationSuiteItems = { /* ... */ },
    layoutType = customNavSuiteType,
) {
    // Content...
}

추가 리소스