Tu App Android con diseño Material con AppBar y Scaffold en Jetpack Compose

A
Antonio Leiva
5 min lectura

Desde hace muchos años, uno de los elementos más identificativos en las Apps Android ha sido la barra superior. Se la ha conocido con muchos nombres: ActionBar, Toolbar, AppBar…

Originalmente esa barra se incluía en las Apps por defecto, y lo único que podíamos hacer era mostrarla u ocultarla, pero poco más.

Con la llegada de Material Design, con sus animaciones, configuraciones de la Toolbar, etc., surgió la necesidad de que esa Toolbar fuera desacoplada y se pudiera incluir en cualquier parte.

Play

¿Pero cómo usamos la Toolbar o AppBar ahora con Compose? En este artículo te voy a explicar esto y te hablaré de pasada sobre Scaffold, un layout que te va a ser de mucha ayuda para crear pantallas típicas de Material.

Configurando la Activity

Como hemos hablado anteriormente, el tema por defecto va a mostrar la barra en la parte superior si no lo decimos lo contrario.

Así que lo primero que le tenemos que decir a la Activity es que nos vamos a encargar nosotros de colocar la AppBar.

<activity
    android:name=".MainActivity"
    android:label="@string/app_name"
    android:theme="@style/Theme.MyMovies.NoActionBar">
    ...
</activity>

Con el tema NoActionBar conseguimos ese objetivo. Si creaste un proyecto nuevo desde cero con soporte para Compose, la Activity que se creó ya tendrá este tema.

Usa Scaffold

Es cierto que, como en los XMLs, podemos tener AppBars independientes que podemos posicionar donde queramos.

Pero si queremos usarla en la posición habitual (en la parte superior de la pantalla), lo ideal es usar el Composable Scaffold.

Scaffold no es más que un layout con unos “huecos” predeterminados que nos permiten configurar aspectos típicos de una App en Android. Entre otros tenemos:

  • topBar: barra superior de navegación. Lo típico es usar una TopAppBar

  • bottomBar: barra inferior de navegación. Se puede usar por ejemplo una BottomAppBar o una BottomNavigation.

  • snackbarHost: sirve para poder mostrar Snackbars de forma sencilla

  • floatingActionButton: hay varias propiedades relacionadas con mostrar ese gran botón circular típico de Material

  • drawer: también tenemos varias propiedades para mostrar un menú lateral desplegable

Todos estos “huecos” realmente aceptan una lambda en la que podemos crear las vistas que necesitemos, no se nos obliga a nada. Pero hay muchos Composables específicos que nos simplificarán la tarea.

Hoy nos vamos a centrar en TopAppBar.

Pero antes vamos a configurar el Scaffold. Lo único que tenemos que hacer es incluir nuestro contenido previo dentro del mismo:

Scaffold {
    MediaList()
}

Hay una cosa que no se nos debe olvidar nunca. Si te fijas, en el IDE se ve que el Scaffold recibe un PaddingValues:

Ese padding lo calcula el layout en función de los componentes que hayamos añadido, y es importante aplicárselo al Composable raíz que añadamos al content.

Así que, tal y como vimos en el artículo de modifiers, vamos a añadir ese parámetro al MediaList, y aplicárselo al parent:

@Composable
fun MediaList(modifier: Modifier = Modifier) {
    LazyVerticalGrid(
        cells = GridCells.Adaptive(150.dp),
        contentPadding = PaddingValues(2.dp),
        modifier = modifier
    ) {
        ...
    }
}

Por último, se lo pasamos a MediaList aplicando el padding:

Scaffold { padding ->
    MediaList(Modifier.padding(padding))
}

Ahora ya estamos listos para pasar a la acción.

TopAppBar: la barra superior de nuestra App

Como casi todos los componentes en Compose, la TopAppBar nos da una configuración estándar muy sencilla con la que trabajar, pero luego podemos hacer muchas cosas para adaptarla a nuestras necesidades.

En su variante más sencilla solo tendríamos que hacer:

Scaffold(
    topBar = {
        TopAppBar(
            title = { Text(stringResource(R.string.app_name)) }
        )
    }
) { ... }

Si te fijas, tanto el argumento topBar como el title de la TopAppBar aceptan una lambda.

Esto ya lo hemos visto en otros ejemplos, y es lo que denominan “Slot API”. El API de Compose deja “huecos” en los que podemos añadir lo que queramos, en vez de asumir que en ese hueco irá un objeto de un tipo concreto.

Por ejemplo el title no te obliga a que sea de tipo Text. Puedes añadir la complejidad que quieras allí. Aquí un ejemplo sencillo, que añade un icono después del texto:

title = {
    Row {
        Text(stringResource(id = R.string.app_name))
        Spacer(Modifier.width(16.dp))
        Icon(Icons.Default.Android, contentDescription = null)
    }
}

TopAppBar: navigationIcon

Podemos definir de forma sencilla un icono de navegación que aparecerá en la parte izquierda. Se nos recomienda que se use un IconButton, que es un icono clickable:

navigationIcon = {
    IconButton(onClick = { /*TODO*/ }) {
        Icon(
            imageVector = Icons.Default.ArrowBack,
            contentDescription = null
        )
    }
}

TopAppBar: Actions

Seguro que vas a necesitar añadir acciones a la barra superior, así que aquí te voy a explicar cómo funcionan.

Al final la sección de acciones no es más que una Row. Así que podemos añadir los elementos que queramos, y estos se colocarán horizontalmente. Lo habitual será usar tambien IconButton:

actions = {
    IconButton(onClick = { /*TODO*/ }) {
        Icon(
            imageVector = Icons.Default.Search,
            contentDescription = null
        )
    }
    IconButton(onClick = { /*TODO*/ }) {
        Icon(
            imageVector = Icons.Default.Share,
            contentDescription = null
        )
    }
}

Si quisieras añadir un menú desplegable con más opciones, la cosa se complica un poco.

Dime en los comentarios si quieres ver otro artículo sobre el tema.

Con lo que ya tenemos, puedes revisar el código en el repositorio de GitHub.

Conclusión

Con esto finalizamos el repaso a Scaffold y a la TopApBar.

Si quieres seguir aprendiendo sobre Jetpack Compose, no te lo pienses y apúntate a Compose Expert.

Si te fijas, el código se nos está yendo un poco de las manos, y como cualquier otra parte de nuestra App, necesita ser estructurado correctamente. En el siguiente vídeo te voy a dar 5 consejos para organizarlo.