Ejemplo práctico 7: Uso básico de Scaffold

Objetivo

En este ejemplo se utiliza Material 3 para añadir un Scaffold con TopAppBar, BottomAppBar, y FloatingActionButton. Además, se utiliza un Snackbar mediante SnackbarHostState y cambio de contenido al pulsar el FAB, mostrando Snackbar cuando el contador alcanza el máximo (5).

Composable ScaffoldMaterial3ConSnackbar

 1@OptIn(ExperimentalMaterial3Api::class)
 2@Composable
 3fun ScaffoldMaterial3ConSnackbar() {
 4    val snackbarHostState = remember { SnackbarHostState() }
 5    val scope = rememberCoroutineScope()
 6    var contador by remember { mutableStateOf(0) }
 7
 8    Scaffold(
 9        snackbarHost = { SnackbarHost(snackbarHostState) },
10        topBar = {
11            TopAppBar(
12                title = { Text("Mi App Simple M3") },
13                colors = topAppBarColors(
14                    containerColor = MaterialTheme.colorScheme.primaryContainer,
15                    titleContentColor = MaterialTheme.colorScheme.primary,
16                )
17            )
18        },
19        bottomBar = {
20            BottomAppBar {
21                IconButton(onClick = { /* Acción 1 */ }) {
22                    Icon(Icons.Default.Home, contentDescription = "Home")
23                }
24                Spacer(Modifier.weight(1f))
25                IconButton(onClick = { /* Acción 2 */ }) {
26                    Icon(Icons.Default.Favorite, contentDescription = "Favoritos")
27                }
28            }
29        },
30        floatingActionButton = {
31            ExtendedFloatingActionButton(
32                onClick = {
33                    if (contador < 5) {
34                        contador++
35                        Log.d("ScaffoldM3", "Contador incrementado: $contador")
36                    } else {
37                        scope.launch {
38                            snackbarHostState.showSnackbar(
39                                "Conteo máximo alcanzado",
40                                actionLabel = "Reiniciar",
41                                duration = SnackbarDuration.Short
42                            ).let { result ->
43                                if (result == SnackbarResult.ActionPerformed) {
44                                    contador = 0
45                                }
46                            }
47                        }
48                    }
49                }
50            ) {
51                Text("Sumar")
52            }
53        },
54        floatingActionButtonPosition = FabPosition.End
55    ) { innerPadding ->
56        Box(
57            modifier = Modifier
58                .fillMaxSize()
59                .padding(innerPadding),
60            contentAlignment = Alignment.Center
61        ) {
62            Text(
63                text = "Conteo: $contador",
64                fontSize = 24.sp,
65                fontWeight = FontWeight.Bold
66            )
67        }
68    }
69}

Para visualizar el ejemplo en la vista previa de Android Studio añade el siguiente método:

1@Preview(showBackground = true)
2@Composable
3fun VistaPrevia() {
4    ScaffoldMaterial3ConSnackbar()
5}

En resumen, se utiliza remember { SnackbarHostState() } para evitar que se cree una nueva en cada recomposición. El Scaffold recibe el snackbarHost, enlazado con el SnackbarHostState creado.

El FAB incrementa contador que, al llegar a 5, mostrará un Snackbar con opción “Reiniciar” y resetea el contador si se pulsa la acción.

innerPadding hace que el contenido central respete las barras del Scaffold.