Większość aplikacji ma kilka miejsc docelowych najwyższego poziomu, które są dostępne w głównym interfejsie nawigacyjnym aplikacji. W kompaktowych oknach, takich jak standardowy wyświetlacz telefonu, miejsca docelowe są zwykle wyświetlane na pasku nawigacyjnym u dołu okna. W rozszerzonym oknie, np. w aplikacji na pełnym ekranie na tablecie, zwykle lepiej sprawdza się szyna nawigacyjna obok aplikacji, ponieważ elementy sterujące nawigacją są łatwiej dostępne, gdy trzymasz urządzenie po lewej i prawej stronie.
NavigationSuiteScaffold upraszcza przełączanie się między interfejsami nawigacji, wyświetlając odpowiednią funkcję kompozycyjną interfejsu nawigacji na podstawie WindowSizeClass. Obejmuje to dynamiczną zmianę interfejsu podczas zmiany rozmiaru okna w czasie działania. Domyślnie wyświetlany jest jeden z tych komponentów interfejsu:
- Pasek nawigacyjny, jeśli szerokość lub wysokość jest kompaktowa albo urządzenie jest w trybie stołowym.
- Kolumna nawigacji w przypadku innych elementów.
NavigationSuiteScaffold wyświetla pasek nawigacyjny w kompaktowych oknach.
NavigationSuiteScaffold wyświetla panel nawigacyjny w rozwiniętych oknach.
Dodawanie zależności
NavigationSuiteScaffold jest częścią biblioteki Material3 adaptive navigation suite. Dodaj zależność z biblioteką w pliku build.gradle aplikacji lub modułu:
Kotlin
implementation("androidx.compose.material3:material3-adaptive-navigation-suite")
Dynamiczny
implementation 'androidx.compose.material3:material3-adaptive-navigation-suite'
Tworzenie szkieletu
Dwie główne części NavigationSuiteScaffold to elementy pakietu nawigacyjnego i treści wybranego miejsca docelowego. Elementy pakietu nawigacyjnego możesz zdefiniować bezpośrednio w funkcji kompozycyjnej, ale często definiuje się je w innym miejscu, np. w wyliczeniu:
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ć NavigationSuiteScaffold, musisz śledzić bieżące miejsce docelowe, co możesz zrobić za pomocą rememberSaveable:
var currentDestination by rememberSaveable { mutableStateOf(AppDestinations.HOME) }
W poniższym przykładzie parametr navigationSuiteItems (typ NavigationSuiteScope) używa funkcji item do definiowania interfejsu nawigacji dla pojedynczego miejsca docelowego. Interfejs miejsca docelowego jest używany na paskach nawigacyjnych, szynach i szufladach. Aby utworzyć elementy nawigacyjne, wykonaj pętlę po AppDestinations (zdefiniowanym 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 funkcji lambda treści docelowej użyj wartości currentDestination, aby określić, który interfejs ma być wyświetlany. Jeśli używasz w aplikacji biblioteki nawigacji, użyj jej tutaj, aby wyświetlić odpowiednie miejsce docelowe. Wystarczy instrukcja when:
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łym obszarze zajmowanym przez rusztowanie, zwykle w całym oknie. Oprócz tego szkielet rysuje konkretny interfejs nawigacyjny, taki jak NavigationBar.
Zarówno interfejs nawigacji, jak i interfejs użytkownika korzystają z wartości określonych w motywie aplikacji, ale możesz je zastąpić.
Parametr containerColor określa kolor powierzchni. Domyślnie jest to kolor tła schematu kolorów. Parametr contentColor określa kolor treści na tej powierzchni. Domyślnie jest to kolor „włączony”
określony dla containerColor. Jeśli na przykład containerColor używa koloru background, contentColor używa koloru onBackground.
Więcej informacji o tym, jak działa system kolorów, znajdziesz w artykule Motywy Material Design 3 w Compose. Zastępując te 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 przed powierzchnią NavigationSuiteScaffold.
Domyślne wartości kolorów interfejsu są dostarczane przez NavigationSuiteDefaults.colors(), ale możesz je zastąpić. Jeśli na przykład chcesz, aby tło paska nawigacyjnego było przezroczyste, ale inne wartości były domyślne, zastąp navigationBarContainerColor:
NavigationSuiteScaffold( navigationSuiteItems = { /* ... */ }, navigationSuiteColors = NavigationSuiteDefaults.colors( navigationBarContainerColor = Color.Transparent, ) ) { // Content... }
Możesz dostosować każdy element w interfejsie nawigacji. Podczas wywoływania funkcji item możesz przekazać instancję NavigationSuiteItemColors. Klasa określa kolory elementów na pasku nawigacyjnym, szynie nawigacyjnej i w panelu nawigacji. Oznacza to, że możesz mieć identyczne kolory w każdym typie interfejsu nawigacji lub możesz je zmieniać w zależności od potrzeb. Zdefiniuj kolory na poziomie NavigationSuiteScaffold, aby używać tej samej instancji 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 zmienia interfejs nawigacji na podstawie klas rozmiaru okna. Możesz jednak zmienić to zachowanie. Jeśli na przykład aplikacja wyświetla pojedynczy duży panel treści dla kanału, może używać stałego panelu nawigacji w przypadku rozszerzonych okien, ale nadal korzystać z działania domyślnego w przypadku kompaktowych i średnich klas rozmiaru okna:
val adaptiveInfo = currentWindowAdaptiveInfo() val customNavSuiteType = with(adaptiveInfo) { if (windowSizeClass.isWidthAtLeastBreakpoint(WIDTH_DP_EXPANDED_LOWER_BOUND)) { NavigationSuiteType.NavigationDrawer } else { NavigationSuiteScaffoldDefaults.calculateFromAdaptiveInfo(adaptiveInfo) } } NavigationSuiteScaffold( navigationSuiteItems = { /* ... */ }, layoutType = customNavSuiteType, ) { // Content... }
Dodatkowe materiały
Wskazówki dotyczące Material Design:
Komponenty biblioteki (
androidx.compose.material3):