39 - Evento touch: dibujar un círculo

Una actividad fundamental es poder detectar cuando el usuario selecciona o toca la pantalla táctil.

Problema:

Desarrollar un programa que dibuje un círculo en la coordenada 100,100. Cuando se presione otra parte de la pantalla táctil proceder a trasladar el círculo a dicha coordenada.

1 - Creamos un proyecto llamado: Proyecto043

Borramos el TextView que agrega automáticamente el Android Studio y definimos el id del RelativeLayout con el valor: layout1:

Canvas Android

Ahora codificamos la clase donde se encuentra toda la lógica para capturar el evento onTouch:

package com.tutorialesprogramacionya.proyecto043

import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import androidx.constraintlayout.widget.ConstraintLayout

class MainActivity : AppCompatActivity() {
    var corx = 0f
    var cory = 0f

    private lateinit var fondo: Lienzo
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val layout1=findViewById<ConstraintLayout>(R.id.layout1)
        val fondo = Lienzo(this)
        layout1.addView(fondo)
        fondo.setOnTouchListener { view, motionEvent ->
            corx = motionEvent.x
            cory = motionEvent.y
            fondo.invalidate()
            true
        }
    }

    inner class Lienzo(context: Context) : View(context) {

        override fun onDraw(canvas: Canvas) {
            canvas.drawRGB(255, 255, 0)
            val pincel1 = Paint()
            pincel1.setARGB(255, 255, 0, 0)
            pincel1.setStrokeWidth(4f)
            pincel1.setStyle(Paint.Style.STROKE)
            canvas.drawCircle(corx, cory, 20f, pincel1)
        }
    }
}

Cuando creamos el objeto fondo de la clase Lienzo llamamos al método setOnTouchListener y le pasamos una función lambda que se ejecuta cada vez que el operador presiona dentro de la componente:

        fondo.setOnTouchListener { view, motionEvent ->
            corx = motionEvent.x
            cory = motionEvent.y
            fondo.invalidate()
            true
        }

Almacenamos en las propiedades corx y cory la coordenada donde el operador presionó con el dedo, pedimos que se vuelva a pintar la componente llamando a invalidate y retornamos true para que siga escuchando eventos si desplaza el dedo el operador.

El método onDraw de la clase Lienzo pinta el fondo de amarillo, crea un objeto de la clase Paint y procede a dibujar un círculo en las coordenadas indicadas por los atributos corx y cory:

        override fun onDraw(canvas: Canvas) {
            canvas.drawRGB(255, 255, 0)
            val pincel1 = Paint()
            pincel1.setARGB(255, 255, 0, 0)
            pincel1.setStrokeWidth(4f)
            pincel1.setStyle(Paint.Style.STROKE)
            canvas.drawCircle(corx, cory, 20f, pincel1)
        }

La clase Lienzo debe ser inner class para poder acceder a las propiedades corx y cory definidas en la clase principal.

La vista previa de la aplicación es:

Canvas Android

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