Panel lateral de navegación

El componente del panel lateral de navegación es un menú deslizante que permite a los usuarios navegar a varias secciones de tu app. Para activarlo, los usuarios deben deslizar el dedo desde el costado o presionar un ícono de menú.

Considera estos tres casos de uso para implementar un panel lateral de navegación:

  • Organización del contenido: Permite que los usuarios cambien entre diferentes categorías, como en las apps de noticias o blogs.
  • Administración de la cuenta: Proporciona vínculos rápidos a la configuración de la cuenta y a las secciones de perfil en apps con cuentas de usuario.
  • Descubrimiento de funciones: Organiza varias funciones y parámetros de configuración en un solo menú para facilitar el descubrimiento y el acceso de los usuarios en apps complejas.

En Material Design, existen dos tipos de paneles laterales de navegación:

  • Estándar: Comparte el espacio de una pantalla con otro contenido.
  • Modal: Aparece sobre otro contenido dentro de una pantalla.
Figura 1: Ejemplo de un panel lateral de navegación.

Ejemplo

Puedes usar el elemento componible ModalNavigationDrawer para implementar un panel lateral de navegación.

Usa el espacio drawerContent para proporcionar un ModalDrawerSheet y el contenido del panel lateral, como en el siguiente ejemplo:

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 acepta una cantidad de parámetros adicionales de panel lateral. Por ejemplo, puedes activar o desactivar si el panel lateral responde a arrastres con el parámetro gesturesEnabled, como en el siguiente ejemplo:

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

Controla el comportamiento

Para controlar cómo se abre y se cierra el panel lateral, usa DrawerState. Debes pasar un DrawerState a ModalNavigationDrawer con el parámetro drawerState.

DrawerState proporciona acceso a las funciones open y close, así como a propiedades relacionadas con el estado actual del panel lateral. Estas funciones de suspensión requieren un CoroutineScope, del que puedes crear una instancia con rememberCoroutineScope. También puedes llamar a las funciones de suspensión en respuesta a eventos de la IU.

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
    }
}

Crea grupos dentro de un panel lateral de navegación

En el siguiente fragmento, se muestra cómo crear un panel lateral de navegación detallado, con secciones y divisores:

@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(Icons.Outlined.Settings, contentDescription = null) },
                        badge = { Text("20") }, // Placeholder
                        onClick = { /* Handle click */ }
                    )
                    NavigationDrawerItem(
                        label = { Text("Help and feedback") },
                        selected = false,
                        icon = { Icon(Icons.AutoMirrored.Outlined.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(Icons.Default.Menu, contentDescription = "Menu")
                        }
                    }
                )
            }
        ) { innerPadding ->
            content(innerPadding)
        }
    }
}

Puntos clave sobre el código

  • Completa el drawerContent con un Column que contiene secciones, divisores y elementos de navegación.
  • ModalDrawerSheet proporciona el diseño de Material Design para el panel lateral.
  • HorizontalDivider separa las secciones dentro del panel lateral.
  • ModalNavigationDrawer crea el panel lateral.
  • drawerContent define el contenido del panel lateral.
  • Dentro de ModalDrawerSheet, un Column organiza los elementos del panel lateral de forma vertical.
  • Los elementos componibles NavigationDrawerItem representan elementos individuales en el panel lateral.
  • Scaffold proporciona la estructura básica de la pantalla, incluido TopAppBar.
  • El navigationIcon en el TopAppBar controla el estado de apertura y cierre del panel lateral.

Resultado

En la siguiente imagen, se muestra cómo aparece el panel lateral cuando se abre, con las secciones y los elementos que se muestran:

Un panel lateral de navegación detallado con dos secciones, cada una con varios íconos y elementos etiquetados.
Figura 2: Se abrió un panel lateral de navegación con dos grupos anidados.

Recursos adicionales