Panel nawigacji

Komponent panel nawigacji to wysuwane menu, które umożliwia użytkownikom przechodzenie do różnych sekcji aplikacji. Użytkownicy mogą je aktywować, przesuwając palcem od boku ekranu lub klikając ikonę menu.

Oto 3 przypadki użycia, w których warto wdrożyć panel nawigacji:

  • Organizacja treści: umożliwia użytkownikom przełączanie się między różnymi kategoriami, np. w aplikacjach z wiadomościami lub blogami.
  • Zarządzanie kontem: udostępniaj szybkie linki do ustawień konta i sekcji profilu w aplikacjach z kontami użytkowników.
  • Odkrywanie funkcji: możesz uporządkować wiele funkcji i ustawień w jednym menu, aby ułatwić użytkownikom ich odkrywanie i dostęp do nich w złożonych aplikacjach.

W Material Design są 2 rodzaje paneli nawigacji:

  • Standardowy: udostępniaj miejsce na ekranie innym treściom.
  • Modalne: pojawiają się nad innymi treściami na ekranie.
Przykład panelu nawigacji Material Design 3 w trybie jasnym i ciemnym.
Rysunek 1. Przykład panelu nawigacji.

Przykład

Do implementacji panelu nawigacji możesz użyć funkcji kompozycyjnej ModalNavigationDrawer.

Użyj boksu drawerContent, aby podać ModalDrawerSheet i zawartość panelu, jak w tym przykładzie:

ModalNavigationDrawer(
    drawerContent = {
        ModalDrawerSheet {
            Text("Drawer title", modifier = Modifier.padding(16.dp))
            HorizontalDivider()
            NavigationDrawerItem(
                label = { Text(text = "Drawer Item") },
                selected = false,
                onClick = { /*TODO*/ }
            )
            // ...other drawer items
        }
    }
) {
    // Screen content
}

ModalNavigationDrawer akceptuje szereg dodatkowych parametrów panelu. Możesz na przykład przełączyć, czy panel boczny ma reagować na przeciąganie, za pomocą parametru gesturesEnabled, jak w tym przykładzie:

ModalNavigationDrawer(
    drawerContent = {
        ModalDrawerSheet {
            // Drawer contents
        }
    },
    gesturesEnabled = false
) {
    // Screen content
}

Zachowanie kontrolne

Aby kontrolować otwieranie i zamykanie panelu, użyj DrawerState. Przekaż DrawerState do ModalNavigationDrawer za pomocą parametru drawerState.

DrawerState zapewnia dostęp do funkcji open i close, a także do właściwości związanych z bieżącym stanem panelu. Te funkcje zawieszające wymagają CoroutineScope, który można utworzyć za pomocą rememberCoroutineScope. Możesz też wywoływać funkcje zawieszające w odpowiedzi na zdarzenia interfejsu.

val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed)
val scope = rememberCoroutineScope()
ModalNavigationDrawer(
    drawerState = drawerState,
    drawerContent = {
        ModalDrawerSheet { /* Drawer content */ }
    },
) {
    Scaffold(
        floatingActionButton = {
            ExtendedFloatingActionButton(
                text = { Text("Show drawer") },
                icon = { Icon(Icons.Filled.Add, contentDescription = "") },
                onClick = {
                    scope.launch {
                        drawerState.apply {
                            if (isClosed) open() else close()
                        }
                    }
                }
            )
        }
    ) { contentPadding ->
        // Screen content
    }
}

Tworzenie grup w panelu nawigacji

Poniższy fragment kodu pokazuje, jak utworzyć szczegółowy panel nawigacji z sekcjami i separatorami:

@Composable
fun DetailedDrawerExample(
    content: @Composable (PaddingValues) -> Unit
) {
    val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed)
    val scope = rememberCoroutineScope()

    ModalNavigationDrawer(
        drawerContent = {
            ModalDrawerSheet {
                Column(
                    modifier = Modifier.padding(horizontal = 16.dp)
                        .verticalScroll(rememberScrollState())
                ) {
                    Spacer(Modifier.height(12.dp))
                    Text("Drawer Title", modifier = Modifier.padding(16.dp), style = MaterialTheme.typography.titleLarge)
                    HorizontalDivider()

                    Text("Section 1", modifier = Modifier.padding(16.dp), style = MaterialTheme.typography.titleMedium)
                    NavigationDrawerItem(
                        label = { Text("Item 1") },
                        selected = false,
                        onClick = { /* Handle click */ }
                    )
                    NavigationDrawerItem(
                        label = { Text("Item 2") },
                        selected = false,
                        onClick = { /* Handle click */ }
                    )

                    HorizontalDivider(modifier = Modifier.padding(vertical = 8.dp))

                    Text("Section 2", modifier = Modifier.padding(16.dp), style = MaterialTheme.typography.titleMedium)
                    NavigationDrawerItem(
                        label = { Text("Settings") },
                        selected = false,
                        icon = { Icon(painter = rememberVectorPainter(AppIcons.Settings), contentDescription = null) },
                        badge = { Text("20") }, // Placeholder
                        onClick = { /* Handle click */ }
                    )
                    NavigationDrawerItem(
                        label = { Text("Help and feedback") },
                        selected = false,
                        icon = { Icon(painter = rememberVectorPainter(AppIcons.Help), contentDescription = null) },
                        onClick = { /* Handle click */ },
                    )
                    Spacer(Modifier.height(12.dp))
                }
            }
        },
        drawerState = drawerState
    ) {
        Scaffold(
            topBar = {
                TopAppBar(
                    title = { Text("Navigation Drawer Example") },
                    navigationIcon = {
                        IconButton(onClick = {
                            scope.launch {
                                if (drawerState.isClosed) {
                                    drawerState.open()
                                } else {
                                    drawerState.close()
                                }
                            }
                        }) {
                            Icon(painter = rememberVectorPainter(AppIcons.Menu), contentDescription = "Menu")
                        }
                    }
                )
            }
        ) { innerPadding ->
            content(innerPadding)
        }
    }
}

Najważniejsze informacje o kodzie

  • Wypełnia drawerContent elementem Column zawierającym sekcje, separatory i elementy nawigacyjne.
  • ModalDrawerSheet zapewnia styl Material Design dla panelu.
  • HorizontalDivider oddziela sekcje w panelu.
  • ModalNavigationDrawer tworzy panel boczny.
  • drawerContent definiuje zawartość panelu.
  • Wewnątrz elementu ModalDrawerSheet element Column układa elementy panelu pionowo.
  • Komponenty NavigationDrawerItem reprezentują poszczególne elementy w panelu.
  • Scaffold zapewnia podstawową strukturę ekranu, w tym TopAppBar.
  • navigationIcon w TopAppBar kontroluje stan otwarcia i zamknięcia panelu.

Wynik

Poniższy obraz pokazuje, jak wygląda otwarty panel z sekcjami i elementami:

Szczegółowy panel nawigacji z 2 sekcjami, z których każda zawiera kilka oznaczonych etykietami elementów i ikon.
Rysunek 2. Otwarty panel nawigacji z 2 grupami zagnieżdżonymi.

Dodatkowe materiały