25 - Canvas - drawLine, drawCircle, drawRect

Como sabemos el API de Compose propone la programación declarativa para crear la interfaz visual de nuestra aplicación. Cuando tenemos que dibujar una línea, un círculo, un rectángulo, rotar, trasladar, escalar etc. Compose también agrega una serie de funciones composables para poder llevar a cabo estas funcionalidades.

Canvas es la función principal para implementar gráficos personalizados en nuestra aplicación. Hacemos la llamada a la función Canvas en forma similar a como creamos Text, Button etc.

Dentro de la función lambda que implementamos asociada a la llamada a Canvas podemos utilizar otro conjunto de funciones para dibujar líneas, círculos, rectángulos etc.

Veamos con un ejemplo sencillo como llamamos a la función Canvas.

Problema

Mostrar dos líneas que inicien y finalicen en los vértices opuestos de la pantalla, un círculo en medio de la pantalla y un rectángulo en la parte superior.

Crearemos el proyecto 'Compose27'

El código a implementar en Kotlin para obtener dicha funcionalidad es:

package com.tutorialesprogramacionya.compose27

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color

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

@Composable
fun PantallaPrincipal() {
    Canvas(modifier = Modifier.fillMaxSize()) {
        val ancho = size.width
        val alto = size.height
        drawLine(
            start = Offset(x = 0f, y = 0f),
            end = Offset(x = ancho, y = alto),
            color = Color.Red,
            strokeWidth = 10f
        )
        drawLine(
            start = Offset(x = ancho, y = 0f),
            end = Offset(x = 0f, y = alto),
            color = Color.Red,
            strokeWidth = 10f
        )
        drawCircle(
            center = Offset(x = ancho / 2, y = alto / 2),
            radius = ancho / 10,
            color = Color.Yellow
        )
        drawRect(
            topLeft = Offset(x = 0f, y = 0f),
            size = Size(ancho*0.50f, alto*0.10f),
            color = Color.Green
        )
    }
}

El resultado de ejecutar este programa es:

Canvas drawLine drawCircle y drawRect Jetpack Compose

En la función composable PantallaPrincipal llamamos a la función composable 'Canvas' (recordemos que siempre podemos consultar sus parámetros disponiendo la flecha del mouse sobre la misma):

Canvas drawLine drawCircle y drawRect Jetpack Compose

El primer parámetro es modifier, en nuestro caso configuramos para que ocupe toda la pantalla llamando a la función 'fillMaxSize'. El segundo parámetro de Canvas es una función lambda que la implementamos con el siguiente código:

    Canvas(modifier = Modifier.fillMaxSize()) {
        val ancho = size.width
        val alto = size.height
        drawLine(
            start = Offset(x = 0f, y = 0f),
            end = Offset(x = ancho, y = alto),
            color = Color.Red,
            strokeWidth = 10f
        )
        drawLine(
            start = Offset(x = ancho, y = 0f),
            end = Offset(x = 0f, y = alto),
            color = Color.Red,
            strokeWidth = 10f
        )
        drawCircle(
            center = Offset(x = ancho / 2, y = alto / 2),
            radius = ancho / 10,
            color = Color.Yellow
        )
        drawRect(
            topLeft = Offset(x = 0f, y = 0f),
            size = Size(ancho*0.50f, alto*0.10f),
            color = Color.Green
        )
    }

Dentro de la función lambda tenemos acceso a un campo llamado 'size' que tiene almacenado el ancho y alto del Canvas (datos muy útiles para saber el espacio que disponemos para dibujar)

Para dibujar una línea disponemos de la función drawLine (no es una función composable, por ello está codificada en minúscula) que nos permite dibujar una línea. Dispone de algunos parámetros obligatorios y otros que toman valores por defecto (presionando con el mouse el nombre de la función teniendo presionada la tecla Control podemos acceder a su implementación):

drawLine Jetpack Compose

color, start y end son obligatorios, la primer línea se inicia en el vértice superior izquierdo (0,0) y llega a la coordenada que coincide con el ancho y alto de nuestro Canvas:

        drawLine(
            start = Offset(x = 0f, y = 0f),
            end = Offset(x = ancho, y = alto),
            color = Color.Red,
            strokeWidth = 10f
        )

Para dibujar un círculo disponemos de la función drawCircle, en nuestro ejemplo configuramos solo los tres parámetros obligatorios. Indicamos la coordenada del punto central del círculo, su radio y el color del mismo:

        drawCircle(
            center = Offset(x = ancho / 2, y = alto / 2),
            radius = ancho / 10,
            color = Color.Yellow
        )

Finalmente dibujamos un rectángulo que empieza en la coordenada (0,0) con la mitad del ancho de la pantalla y un 10% del alto:

        drawRect(
            topLeft = Offset(x = 0f, y = 0f),
            size = Size(ancho*0.50f, alto*0.10f),
            color = Color.Green
        )

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