18 - Componente Card (tarjeta)

Otra componente que nos provee Material Design son las tarjetas (Card), para ello Compose dispone de la función composable Card.

El empleo de las tarjetas es agrupar contenido y acciones sobre un solo tema de nuestra aplicación.

Problema

Confeccionar una aplicación que muestre la bandera, nombre del país y cantidad de habitantes de 3 países. Mostrar cada país en una tarjeta separada (Card)

Crear un proyecto llamado Compose20, la interfaz visual de la misma debe ser similar a:

Card Jetpack Compose

El código fuente que debemos implementar es:

package com.tutorialesprogramacionya.compose20

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.Card
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import java.text.DecimalFormat


class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            Listado(paises = paises)
        }
    }
}

data class Pais(val nombre: String, val cantidadHabitantes: Int, val bandera: Int)

val paises = listOf<Pais>(
    Pais("Argentina", 44000000, R.drawable.argentina),
    Pais("Brasil", 211000000, R.drawable.brasil),
    Pais("Colombia", 50000000, R.drawable.colombia)
)

@Composable
fun Listado(paises: List<Pais>) {
    LazyColumn {
        items(paises) { pais ->
            Tarjeta(pais)
        }
    }
}

@Composable
fun Tarjeta(pais: Pais) {
    Card(
        elevation = 5.dp,
        modifier = Modifier
            .padding(10.dp)
            .fillMaxWidth()
    ) {
        Row(modifier = Modifier.padding(6.dp)) {
            Image(
                painter = painterResource(id = pais.bandera),
                contentDescription = null,
                contentScale = ContentScale.Crop,
            )
            Spacer(modifier = Modifier.width(10.dp))
            Column() {
                Text(
                    text = pais.nombre,
                    style = MaterialTheme.typography.h3
                )
                Text(
                    text = "${DecimalFormat("###,###,###").format(pais.cantidadHabitantes)} habitantes",
                    style = MaterialTheme.typography.body1
                )
            }

        }
    }
}

Declaramos un data class para luego pasar a definir una lista con tres elementos de dicha clase:

data class Pais(val nombre: String, val cantidadHabitantes: Int, val bandera: Int)

val paises = listOf<Pais>(
    Pais("Argentina", 44000000, R.drawable.argentina),
    Pais("Brasil", 211000000, R.drawable.brasil),
    Pais("Colombia", 50000000, R.drawable.colombia)
)

La primer función recorre la lista de países y llamamos a la segunda función composable que mostrará cada pais:

@Composable
fun Listado(paises: List<Pais>) {
    LazyColumn {
        items(paises) { pais ->
            Tarjeta(pais)
        }
    }
}

La función tarjeta recibe un objeto de la clase Pais y procede a llamar a la función composable Card, pasando como parámetro la elevación (el cual permite ver una sombra en el borde de la tarjeta), luego también iniciamos el parámetro modifier, llamando al método padding y fillMaxWidth para que las tarjetas ocupen todo el espacio en el ancho:

@Composable
fun Tarjeta(pais: Pais) {
    Card(
        elevation = 5.dp,
        modifier = Modifier
            .padding(10.dp)
            .fillMaxWidth()
    ) {
        Row(modifier = Modifier.padding(6.dp)) {
            Image(
                painter = painterResource(id = pais.bandera),
                contentDescription = null,
                contentScale = ContentScale.Crop,
            )
            Spacer(modifier = Modifier.width(10.dp))
            Column() {
                Text(
                    text = pais.nombre,
                    style = MaterialTheme.typography.h3
                )
                Text(
                    text = "${DecimalFormat("###,###,###").format(pais.cantidadHabitantes)} habitantes",
                    style = MaterialTheme.typography.body1
                )
            }

        }
    }
}

El contenido de la tarjeta lo disponemos dentro de una fila. El primer elemento es la bandera y luego para que el nombre del país y la cantidad de habitantes aparezcan uno debajo del otro debemos llamar a la función Column.

Este proyecto lo puede descargar en un zip desde este enlace: Compose20.zip