Większość aplikacji ma kilka miejsc docelowych najwyższego poziomu, do których można dotrzeć za pomocą głównego interfejsu nawigacji aplikacji. W oknach kompaktowych, takich jak standardowy wyświetlacz telefonu, miejsca docelowe są zwykle wyświetlane na pasku nawigacji u dołu okna. W rozwiniętym oknie, np. aplikacji pełnoekranowej na tablecie, pasek nawigacyjny obok aplikacji jest zwykle lepszym wyborem, ponieważ elementy sterujące nawigacją są łatwiej dostępne, gdy trzymasz urządzenie w rękach po lewej i po prawej stronie.
NavigationSuiteScaffold
upraszcza przełączanie się między interfejsami nawigacji, wyświetlając odpowiedni komponent interfejsu nawigacji na podstawie WindowSizeClass
. Obejmuje to dynamiczną zmianę interfejsu podczas zmiany rozmiaru okna w czasie działania. Domyślnie wyświetlane są te elementy interfejsu:
- Pasek nawigacyjny, jeśli szerokość lub wysokość jest niewielka albo urządzenie jest w pozycji poziomej.
- Kolumna nawigacji do wszystkich pozostałych treści
Dodawanie zależności
NavigationSuiteScaffold
należy do biblioteki kompletu dostosowanej nawigacji Material3. Dodaj zależność biblioteki w pliku build.gradle
aplikacji lub modułu:
Kotlin
implementation("androidx.compose.material3:material3-adaptive-navigation-suite")
Groovy
implementation 'androidx.compose.material3:material3-adaptive-navigation-suite'
Tworzenie rusztowania
NavigationSuiteScaffold
składa się z 2 głównych części: elementów pakietu nawigacyjnego i treści dotyczących wybranego miejsca docelowego. Elementy zestawu nawigacyjnego możesz zdefiniować bezpośrednio w komponowalnym komponencie, ale często definiuje się je gdzie indziej, na przykład w enumeracji:
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), }
Aby używać funkcji NavigationSuiteScaffold
, musisz śledzić bieżące miejsce docelowe. Możesz to robić za pomocą funkcji rememberSaveable
:
var currentDestination by rememberSaveable { mutableStateOf(AppDestinations.HOME) }
W tym przykładzie parametr navigationSuiteItems
(typu NavigationSuiteScope
) używa funkcji item
, aby zdefiniować interfejs nawigacji dla poszczególnych miejsc docelowych. Interfejs docelowy jest używany na paskach nawigacyjnych, paskach bocznych i w drawerach. Aby utworzyć elementy nawigacji, możesz przejść w pętli przez element AppDestinations
(zdefiniowany w poprzednim fragmencie kodu):
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. }
W ramach docelowej funkcji lambda treści użyj wartości currentDestination
, aby określić, jakie UI ma się wyświetlać. Jeśli w aplikacji używasz biblioteki nawigacji, możesz jej użyć, aby wyświetlić odpowiednie miejsce docelowe. Wyrażenie warunkowe może wystarczyć:
NavigationSuiteScaffold( navigationSuiteItems = { /*...*/ } ) { // Destination content. when (currentDestination) { AppDestinations.HOME -> HomeDestination() AppDestinations.FAVORITES -> FavoritesDestination() AppDestinations.SHOPPING -> ShoppingDestination() AppDestinations.PROFILE -> ProfileDestination() } }
Zmień kolory
NavigationSuiteScaffold
tworzy Surface
na całej powierzchni, którą zajmuje rusztowanie, zazwyczaj na całym oknie. Dodatkowo szablon generuje interfejs nawigacji, np. NavigationBar
.
Zarówno interfejs użytkownika, jak i interfejs nawigacji korzystają z wartości określonych w motywie aplikacji, ale możesz je zastąpić.
Parametr containerColor
określa kolor powierzchni. Domyślny kolor to kolor tła Twojego schematu kolorów. Parametr contentColor
określa kolor treści na tej powierzchni. Domyślnie jest to kolor „włączony” z ustawienia containerColor
. Jeśli na przykład containerColor
używa koloru background
, to contentColor
używa koloru onBackground
.
Więcej informacji o tym, jak działa system kolorów, znajdziesz w artykule Motyw Material Design 3 w Compose. Podczas zastępowania tych wartości używaj wartości zdefiniowanych w motywie, aby aplikacja obsługiwała tryby wyświetlania ciemnego i jasnego:
NavigationSuiteScaffold( navigationSuiteItems = { /* ... */ }, containerColor = MaterialTheme.colorScheme.primary, contentColor = MaterialTheme.colorScheme.onPrimary, ) { // Content... }
Interfejs nawigacji jest wyświetlany na wierzchu powierzchni NavigationSuiteScaffold
.
Domyślne wartości kolorów interfejsu są dostarczane przez NavigationSuiteDefaults.colors()
, ale możesz też zastąpić te wartości. Jeśli np. chcesz, aby tło paska nawigacyjnego było przezroczyste, a inne wartości miały wartości domyślne, zastąpij navigationBarContainerColor
:
NavigationSuiteScaffold( navigationSuiteItems = { /* ... */ }, navigationSuiteColors = NavigationSuiteDefaults.colors( navigationBarContainerColor = Color.Transparent, ) ) { // Content... }
Ostatecznie możesz dostosować każdy element w interfejsie nawigacji. Podczas wywoływania funkcji item
możesz podać instancję NavigationSuiteItemColors
. Klasa określa kolory elementów na pasku nawigacyjnym, pasku bocznym i drawerze nawigacji. Oznacza to, że możesz używać identycznych kolorów w przypadku każdego typu interfejsu nawigacji lub zmieniać kolory w zależności od potrzeb. Określ kolory na poziomie NavigationSuiteScaffold
, aby używać tego samego obiektu we wszystkich elementach, i wywołaj funkcję NavigationSuiteDefaults.itemColors()
, aby zastąpić tylko te, które chcesz zmienić:
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... }
Dostosowywanie typów nawigacji
Domyślne działanie NavigationSuiteScaffold
polega na zmianie interfejsu nawigacji w zależności od klasyfikacji rozmiaru okna. Możesz jednak zmienić to zachowanie. Jeśli np. Twoja aplikacja wyświetla jeden duży panel treści w ramach kanału, może używać stałego paska nawigacyjnego w przypadku rozwiniętych okien, ale nadal stosować domyślne zachowanie w przypadku okien w klasach rozmiarów kompaktowy i średni:
val adaptiveInfo = currentWindowAdaptiveInfo() val customNavSuiteType = with(adaptiveInfo) { if (windowSizeClass.windowWidthSizeClass == WindowWidthSizeClass.EXPANDED) { NavigationSuiteType.NavigationDrawer } else { NavigationSuiteScaffoldDefaults.calculateFromAdaptiveInfo(adaptiveInfo) } } NavigationSuiteScaffold( navigationSuiteItems = { /* ... */ }, layoutType = customNavSuiteType, ) { // Content... }
Dodatkowe materiały
Wskazówki dotyczące Material Design:
androidx.compose.material3
komponenty biblioteki: