Taula de continguts

Android Canvas : Views Personalitzades

Article de referència: Android

En aquest article veiem com crear una View o widget personalitzat, dibuixant directament sobre ell amb l'objecte Canvas.

, , , , , , ,


Crear una nova View

Ves a la carpeta amb els arxius de codi Kotlin/Java i clica amb el botó dret o vés a:

File -> New -> Kotlin Class/File

Posa-li el nom que desitgis, per exemple Display:

Display.kt
class Display @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
 
    private val paint = Paint().apply {
        color = Color.BLUE
        style = Paint.Style.FILL
        isAntiAlias = true
    }
 
    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
 
        // Fons
        canvas.drawColor(Color.WHITE)
 
        // pintem un quadrat del 25% al 75% de l'alçada i amplada
        canvas.drawRect(
            width * 0.25f,  // left
            height * 0.75f, // top
            width * 0.75f,  // right
            height * 0.25f, // bottom
            paint)
 
    }
}

Fixa't en què:


Afegeix la nova classe al layout

La manera més fàcil és afegir una View genèrica amb la interfície gràfica, amb els tamanys que ens convingui, i després anar al codi XML i canviar el tipus de widget per la nova class que hem creat.

Canviariem l'element <View …> per <com.myuser.myapp.MyClass …>

Segurament quedaria similar a aquest exemple (dins d'una constraint layout):

activity_main.xml
<com.myuser.myapp.Display
    android:id="@+id/display"
    android:layout_width="300dp"
    android:layout_height="300dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />


Aplicar canvis als dibuixos sobre el widget

El més còmode per dibuixar-hi de forma dinàmica és posar el codi dins de la nova classe Display i repintar sempre tota la View.

Per forçar que es repinti podem cridar la funció View.invalidate(), la qual acabarà amb la crida a onDraw que hem implementat:

  val display = findViewById<Display>(R.id.display)
  display.invalidate()