Saltar a contenido

95. Interfaz de usuario. Composable

flowchart TD A[Kotlin] -->|conocimiento básico| B(Interfaz de Usuario) B --> C{Composable} C -->|One| D[Box] C -->|Two| E[Componentes] C -->|Three| F[ Modifier] B --> G[State] B --> H[Navigation]

95.1 Componentes básicos Compose

Tenemos coponentes contenedores y finales (widget) Contenedores

  • Surface : Contiene componentes a los que se aplica un tema.
  • Box: Contenedor que puede apilar componentes.
  • Row: Coloca elementos en una fila horizontal.
  • Column: Coloca elementos en una columna vertical.
  • LazyColumn: Lista vertical desplazable que recicla elementos.
  • LazyRow: Lista horizontal desplazable que recicla elementos.
  • Card: Contenedor con sombra y esquinas redondeadas.
  • Scaffold: Estructura básica de Material Design con componentes de app bar, FAB, etc.
  • ModalDrawer: Menú de navegación que se desliza lateralmente.

Widget

  • Text: Muestra texto. No sirve de entrada de texto
  • Button: Botón interactivo.
  • TextField: Entrada de texto del usuario.
  • Image: Muestra imágenes.
  • IconButton: Botón que contiene un icono.
  • Slider: Control deslizante para seleccionar valores.
  • Switch: Interruptor de encendido/apagado.
  • Checkbox: Casilla de verificación.
  • RadioButton: Botón de opción para selecciones exclusivas.
  • FloatingActionButton: Botón de acción flotante.
  • Divider: Línea para separar contenido.
  • Spacer: Componente para agregar espacio.
  • ProgressBar: Muestra el progreso de una tarea.
  • AlertDialog: Muestra alertas y diálogos.
  • BottomNavigation: Navegación en la parte inferior de la pantalla.
  • TabRow: Pestañas de navegación.

95.2 Surface

  • Es un bloque contenedor de componentes, y propiedades como color.
  • Es necesario que tenga modificadores de tamaño
  • SOLO ADMITE UN COMPONENTE.
  • Se pueden anidar Surface (background distintos)
@Composable
fun MainScreen(){
    Surface(
        color= Color.LightGray,
        modifier= Modifier.fillMaxWidth()
    )

95.3 Box

Box esotro contenedor que se utiliza para alinear otros Composables en un área rectangular.

Se puede usar Box como un contenedor para organizar Composables en el diseño. Dentro de Box, puedes agregar otros Composables y controlar su posición y alineación.

*Propiedades de Alineación

  • contentAlignment: Controla la alineación de todos los Composables dentro de la Box. Esto es útil cuando deseas que todos los elementos dentro de la Box se alineen de la misma manera.

  • Modificadores Al igual que otros Composables en Jetpack Compose, puedes aplicar modificadores a una Box para cambiar su apariencia o comportamiento. Por ejemplo, puedes establecer un fondo o cambiar su tamaño utilizando modificadores.

@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
    Text(
        text = "Hello $name!",
        modifier = modifier
    )
}

@Preview(showBackground = true,
    name="App saludo",
    widthDp = 400,
    heightDp = 200)
@Composable
fun GreetingPreview() {
    EjemploTheme {
        Box {
            Greeting("Android")
        }
    }
}
Se vería asi: Alt text

Para que Box ocupe todo el espacio usaremos Modifier:

fun GreetingPreview() {
    EjemploTheme {
        Box (
            modifier = Modifier.fillMaxSize()
        ){
            Greeting("Android")
            //Greeting("Roberto")
        }
    }
}

95.4 Row , Column

95.5 Text

@Composable
fun Text(
    text: String,
    modifier: Modifier = Modifier,
    color: Color = Color.Unspecified,
    fontSize: TextUnit = TextUnit.Unspecified,
    fontStyle: FontStyle? = null,
    fontWeight: FontWeight? = null,
    fontFamily: FontFamily? = null,
    letterSpacing: TextUnit = TextUnit.Unspecified,
    textDecoration: TextDecoration? = null,
    textAlign: TextAlign? = null,
    lineHeight: TextUnit = TextUnit.Unspecified,
    overflow: TextOverflow = TextOverflow.Clip,
    softWrap: Boolean = true,
    maxLines: Int = Int.MAX_VALUE,
    onTextLayout: (TextLayoutResult) -> Unit = {},
    style: TextStyle = LocalTextStyle.current
)
* text el texto a mostrar * color: Color. ( androidx.compose.ui.graphics.Color) Representa un color en formato ARGB y otros. Se puede usar con: * Definido en hex: val Purple200 = Color(0xFFBB86FC) o bien: val Blue = Color(red = 0f, green = 0f, blue = 1f) * Usando : val rojo = Color.Red * Usando un recurso: color = colorResource(R.color.purple_200) * fontSize: TextUnit. Unidades de medida de texto, sp (Scale-independent Pixels) o em. Las sp son las más comunes para el texto, ya que se escalan con las preferencias de tamaño de texto del usuario y la densidad de pantalla. em en escala del font. Por ejemplo si el font son 16 pixel, 1.em son 16 pixel. * fontWeight: FontWeight. Grosor del texto (negrita, etc). Los valores de FontWeight comúnmente utilizados incluyen: * FontWeight(600), algo más grueso de normal, menos que bold. * FontWeight.Normal (equivalente a 400): El peso estándar o normal de la fuente. * FontWeight.Bold (equivalente a 700): Un peso más grueso, comúnmente utilizado para resaltar o enfatizar texto. * También hay otros valores como Light (300), Medium (500), SemiBold (600), ExtraBold (800), y Black (900), que proporcionan diferentes niveles de grosor. * fontFamily: FontFamily? . permite especificar una familia de fuentes tipográficas. Tenemos: * Fuentes Incorporadas: Jetpack Compose incluye algunas familias de fuentes predeterminadas como Serif, SansSerif, y Monospace * Fuentes Personalizadas: Puedes definir tu propia FontFamily utilizando fuentes personalizadas. Esto se hace cargando archivos de fuente (como .ttf o .otf) y asignándolos a una FontFamily. * letterSpacing: TextUnit. Aumenta la separación entre caracteres
Text(text = "Texto de ejemplo", letterSpacing = 0.5.em)
* textDecoration: TextDecoration?. Puede ser: * Underline: Aplica un subrayado al texto. * LineThrough: Aplica un tachado al texto. * textAlign TextAlign?. Para especificar la alineación horizontal del texto dentro de un composable Text. Esta propiedad es crucial para controlar cómo se presenta el texto en relación con el espacio disponible en su contenedor. TextAlign ofrece varias opciones para la alineación del texto, incluyendo:

  • Start: Alinea el texto al inicio del contenedor. En un entorno de izquierda a derecha (LTR), esto significa alinear a la izquierda, y en un entorno de derecha a izquierda (RTL), alinear a la derecha.
  • End: Alinea el texto al final del contenedor. En un entorno LTR, esto significa alinear a la derecha, y en un entorno RTL, alinear a la izquierda.
  • Center: Centra el texto horizontalmente en el contenedor.
  • Justify: Ajusta el espaciado de las palabras de manera que el texto ocupe completamente el ancho del contenedor, creando un borde uniforme en ambos lados.
  • lineHeight: TextUnit. Controla la distancia vertical entre líneas de texto.
  • overflow: TextOverflow = TextOverflow.Clip. Controla como se comporta el texto cuando se excede el límite de su contenedor. Se suele usar con masLines . Modos Comunes
  • Clip: Con este modo, el texto que excede el espacio disponible simplemente se corta, sin indicar visualmente que hay más texto.
  • Ellipsis: Este es probablemente el modo más común. Agrega puntos suspensivos ("...") al final del texto visible para indicar que hay más texto que no se está mostrando.
  • Visible: En este modo, el texto se dibuja fuera de su contenedor, lo que puede llevar a que se superponga con otros elementos de la interfaz de usuario.

  • softWrap:

  • maxLines:Boolean . Si softWrap está establecido en true, el texto se ajustará automáticamente a la línea siguiente al llegar al final del contenedor. Si está en false, el texto continuará en la misma línea, potencialmente desbordando el contenedor.
  • onTextLayout: (TextLayoutResult) -> Unit . es un callback que se puede utilizar con el composable Text para obtener información detallada sobre el layout del texto una vez que ha sido colocado y medido en la interfaz de usuario. Proporciona un TextLayoutResult, que contiene información detallada sobre el layout del texto después de que se ha medido y colocado en la pantalla.
    Text(
        text = "Ejemplo de texto",
        onTextLayout = { textLayoutResult ->
            // Aquí puedes acceder a la información del layout
        }
    )
    
  • style: TextStyle

95.6 TextField

Este composable proporciona un campo de texto editable, utilizado comúnmente para permitir a los usuarios introducir texto en una aplicación. Es uno de los componentes básicos en la creación de interfaces de usuario interactivas. Ejemplo:

var text by remember { mutableStateOf("") }

TextField(
    value = text,
    onValueChange = { text = it }
)
En este ejemplo, text es una variable de estado que mantiene el texto actual del TextField. onValueChange se llama cada vez que el usuario cambia el texto, actualizando la variable text.

Personalización: TextField ofrece una amplia gama de opciones para personalizar su apariencia y comportamiento, incluyendo:

  • placeholder: Para mostrar un texto de sugerencia cuando el campo está vacío.
  • leadingIcon y trailingIcon: Para agregar íconos dentro del campo de texto.
  • colors: Para personalizar los colores del texto, fondo, cursor, etc.
  • keyboardOptions: Para configurar opciones del teclado, como el tipo de teclado (numérico, de texto, etc.) y las acciones del teclado (como "Siguiente", "Hecho", etc.).

Manejo de Estado: El estado del texto en un TextField se maneja a través de una variable de estado (mutableStateOf). Esto asegura que el campo de texto se actualice correctamente en respuesta a los cambios de entrada del usuario.

Validación y Control de Errores: Puedes implementar lógica de validación y control de errores para TextField. Por ejemplo, puedes cambiar el color del borde o mostrar un mensaje de error si el texto introducido no cumple con ciertos criterios.

Estilos de Texto: TextField permite personalizar el estilo del texto mostrado, como el tamaño de fuente, el color y el peso de la fuente, utilizando la propiedad textStyle.

Seguridad del Texto : Para entradas sensibles como contraseñas, puedes usar VisualTransformation para ocultar el texto mostrado, como en PasswordVisualTransformation().

Accesibilidad: TextField admite características de accesibilidad, como la etiqueta de contenido para lectores de pantalla, lo que es crucial para crear aplicaciones inclusivas.

Variantes: Además del TextField básico, Jetpack Compose también ofrece OutlinedTextField y BasicTextField. OutlinedTextField tiene un estilo con un borde alrededor, mientras que BasicTextField es una versión más baja en características y personalización, útil para casos más controlados y personalizados.

95.7 Modifier. Modificadores de componibles

Los modificadores te permiten decorar o aumentar un elemento componible. Por ejemplo, puedes hacer todo esto:

  • Cambiar el tamaño, el diseño, el comportamiento y el aspecto del elemento componible
  • Agregar información (p. ej., etiquetas de accesibilidad)
  • Procesar entradas del usuario
  • Agregar interacciones de nivel superior, (p. ej., hacer que un elemento sea apto para hacer clic, desplazable, arrastrable o ampliable)
  • Los modificadores son objetos estándar de Kotlin. Para crear uno, llama a una de las funciones de clase Modifier.

En los Modifier se pueden encadenar llamadas:

@Composable
private fun Greeting(name: String) {
  Column(modifier = Modifier
    .padding(24.dp)
    .fillMaxWidth()
  ) {
    Text(text = "Hello,")
    Text(text = name)
  }
}

** El orden de los modificadores es importante**
Cada función incluye cambios en el Modifier y el orden influye en el resultado final, por ejemplo:

@Composable
fun ArtistCard(/*...*/) {
    val padding = 16.dp
    Column(
        Modifier
            .clickable(onClick = onClick)
            .padding(padding)
            .fillMaxWidth()
    ) {
        // rest of the implementation
    }
}
Con el código anterior se puede pulsar en todo el área incluido el padding.

Si cambiamos el orden:

@Composable
fun ArtistCard(/*...*/) {
    val padding = 16.dp
    Column(
        Modifier
            .padding(padding)
            .clickable(onClick = onClick)
            .fillMaxWidth()
    ) {
        // rest of the implementation
    }
}
El espacio que define padding no reacciona a las pulsaciones.

95.7.0.1 MOdificadores integrados

** Padding y tamaño**

@Composable
fun ArtistCard(/*...*/) {
    Row(
        modifier = Modifier.size(width = 400.dp, height = 100.dp)
    ) {
        Image(/*...*/)
        Column { /*...*/ }
    }
}

Una lista completa de modificadores en android developer

95.8 Imagenes y gráficos

95.8.1 Cargar imagenes

Desde Disco
Usamos el elemento componible Image para cargar imagenes de formato PNG,JPEG,WEBP o vectorial. Cuando cargamos de disco usamos la API de painterResource

Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_description)
)
En el ejemplo anterior, se usa un stringResource() para cargar la descripción del contenido traducido desde el archivo strings.xml

Compatibilidad con elementos de diseño Actualmente, painterResource admite los siguientes tipos de elementos de diseño:

  • AnimatedVectorDrawable
  • BitmapDrawable (PNG, JPG, WEBP)
  • ColorDrawable
  • VectorDrawable

Desde Internet

Se tiene que utilizar una librería externa de forma que maneje el cache y la lógica de red (asíncrona). Por ejemplo la librería Coil
Necesitamos la dependencia

implementation("io.coil-kt:coil-compose:2.5.0")
y usamos AsyncImage :
AsyncImage(
    model = "https://example.com/image.jpg",
    contentDescription = "Translated description of what the image contains"
)

95.8.2 Imagenes de bit frente a imagenes vectoriales

95.8.3 Iconos de Material

Usamos el elemento componible ***Icon** que sigue las directrices de Material Design
Debemos incluir la dependencia para Compose Material 3

[TODO]

95.8.4 Personalizar una imagen

Las imágenes se pueden personalizar con propiedades en un elemento componible Image (contentScale, colorFilter). También puedes aplicar los Modifiers existentes para producir diferentes efectos en Image. Los modificadores se pueden usar en cualquier elemento componible, no solo en el elemento componible Image, mientras que contentScale y colorFilter son parámetros explícitos en este elemento componible Image

[TODO]`

95.9 Button

Tradicional botón.

Button
@Composable
fun Button(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    shape: Shape = ButtonDefaults.shape,
    colors: ButtonColors = ButtonDefaults.buttonColors(),
    elevation: ButtonElevation? = ButtonDefaults.buttonElevation(),
    border: BorderStroke? = null,
    contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
    content: @Composable RowScope.() -> Unit
): Unit

Ejemplo

Button(
    onClick = { /* ... */ },
    // Uses ButtonDefaults.ContentPadding by default
    contentPadding = PaddingValues(
        start = 20.dp,
        top = 12.dp,
        end = 20.dp,
        bottom = 12.dp
    )
) {
    // Inner content including an icon and a text label
    Icon(
        Icons.Filled.Favorite,
        contentDescription = "Favorite",
        modifier = Modifier.size(ButtonDefaults.IconSize)
    )
    Spacer(Modifier.size(ButtonDefaults.IconSpacing))
    Text("Like")
}
El último parámetro en una función lambda final ( parametro content de tipo RowScope ). Este es un espacio que admite composición en una fila (es decir para poner cualquier cosa como texto o imganes en el botón.).
(Mas detalles esta web)

95.10 Listas y Grid

Se utilizan LazyColumn y LazyRow de Compose. Estos componentes están diseñados para ser eficientes con listas largas.

### LazyColumn

Los elementos de la lista se componen con elementos item e items.

items se utiliza para mostrar listas de elementos como en el siguiente ejemplo:

```Kotlin // ... import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items

@Composable fun Conversation(messages: List) { LazyColumn { items(100) { message -> MessageCard(message) // cualquier composable } } }

@Preview @Composable fun PreviewConversation() { ComposeTutorialTheme { Conversation(SampleData.conversationSample) } }

```

95.11 Scalfold

95.12 ViewModel y Livedata

Continua en esta página

95.13 Apendice

Versión v0.8, 2-11-23

95.14 Indice