Matrix — una clase del SDK de Android (android.graphics.Matrix) que representa una transformación afín mediante una matriz 3×3. Se utiliza para transformar objetos gráficos — mover, escalar, rotar y sesgar. Según la Documentación para Desarrolladores de Android (2026), Matrix es la herramienta principal para trabajar con transformaciones en Canvas, Bitmap y Drawable, proporcionando un control preciso de coordenadas en el dibujo personalizado.
Puntos Clave
Matrix (android.graphics.Matrix) — una clase del SDK de Android que representa una matriz matemática 3×3 utilizada para transformar coordenadas bidimensionales. Matrix es el bloque fundamental para todas las transformaciones gráficas en Android — desde el movimiento y escalado de Canvas hasta complejas distorsiones de perspectiva de Bitmap.
A diferencia de iOS, que utiliza estructuras separadas CGAffineTransform (afines) y CATransform3D (3D), Android combina transformaciones afines y de perspectiva en una sola clase Matrix. La matriz 3×3 permite representar tanto operaciones afines estándar (última fila [0, 0, 1]) como distorsiones de perspectiva donde la última fila contiene valores arbitrarios. Esto proporciona más flexibilidad, pero requiere comprensión de la matemática matricial.
Matrix está estrechamente integrado con la API de Canvas. Cuando un desarrollador llama a canvas.translate(), canvas.scale() o canvas.rotate(), estos métodos modifican internamente la matriz del contexto gráfico. Puede obtener la matriz actual de Canvas mediante canvas.getMatrix() y aplicar manualmente una personalizada con canvas.setMatrix() o canvas.concat().
Matrix admite cuatro tipos básicos de transformaciones afines: translate, scale, rotate, skew (sesgar). Cada tipo tiene métodos para pre-multiplicación (pre), post-multiplicación (post) y establecimiento (set). La diferencia entre preTranslate y postTranslate radica en el orden de multiplicación de matrices, lo que afecta la transformación final al combinar operaciones.
| Operación | Método | Parámetros | Descripción |
|---|---|---|---|
| Trasladar | setTranslate / preTranslate / postTranslate | dx, dy | Desplazamiento en los ejes X e Y |
| Escalar | setScale / preScale / postScale | sx, sy, px, py | Escalado con punto de pivote |
| Rotar | setRotate / preRotate / postRotate | degrees, px, py | Rotación alrededor del punto de pivote |
| Sesgar | setSkew / preSkew / postSkew | kx, ky | Inclinación (cizalladura) a lo largo de los ejes |
Translate cambia la posición de todos los puntos mediante un desplazamiento dx, dy. Un dx positivo desplaza hacia la derecha, dy — hacia abajo (en el sistema de coordenadas de pantalla de Android, el eje Y apunta hacia abajo). Translate no cambia la forma del objeto — solo su posición. Es la operación más simple y más utilizada para posicionar elementos.
Scale cambia el tamaño de un objeto con factores sx (en X) y sy (en Y). Los parámetros px, py especifican el punto de pivote para el escalado. Si px, py no se especifican, el escalado se realiza respecto al origen (0, 0). Cuando sx = sy, el objeto escala uniformemente. Los valores negativos crean un reflejo.
Rotate rota un objeto un ángulo dado (en grados) alrededor de un punto de pivote (px, py). Los grados positivos corresponden a rotación en sentido horario (a diferencia de iOS/macOS, donde un ángulo positivo es antihorario). Si px, py no se establecen, la rotación se realiza alrededor del origen.
Skew (cizalladura) deforma un objeto inclinándolo a lo largo del eje X (kx) o del eje Y (ky). Un valor de 1.0 inclina 45 grados. Skew se utiliza para crear efectos de inclinación, apariencias pseudo-3D y distorsión de perspectiva.
Matrix almacena sus elementos 3×3 en un array interno de 9 valores de punto flotante (float[9]). El orden de almacenamiento es por columnas (column-major), consistente con la representación matemática estándar. El acceso a elementos individuales se realiza mediante constantes: Matrix.MSCALE_X, Matrix.MSKEW_Y, Matrix.MTRANS_X y así sucesivamente.
La matriz está organizada de la siguiente manera: las dos primeras columnas (MSCALE_X, MSKEW_X, MSKEW_Y, MSCALE_Y) manejan escalado, rotación y sesgado. La tercera columna (MTRANS_X, MTRANS_Y, MPERSP_2) maneja traslación y perspectiva. Para transformaciones afines, MPERSP_0 y MPERSP_1 son 0, y MPERSP_2 es 1.
Para obtener los valores de la matriz, use getValues(float[] values), que llena un array de 9 elementos. Para establecerlos, use setValues(float[] values). Esto permite la manipulación directa de la matriz para transformaciones personalizadas complejas más allá de los métodos estándar translate, scale, rotate y skew.
Matrix proporciona varios métodos para clasificar el estado actual. isIdentity() verifica si la matriz es identidad. isAffine() verifica si contiene solo transformaciones afines (MPERSP_0 = 0, MPERSP_1 = 0, MPERSP_2 = 1). Estas comprobaciones son útiles para la optimización: si la matriz es identidad, la transformación se puede omitir.
Matrix admite varias categorías de operaciones: establecimiento (set), pre-multiplicación (pre), post-multiplicación (post), concatenación (concat), inversión (invert) y mapeo (map). Cada categoría tiene su propósito al construir transformaciones complejas.
preTranslate multiplica la matriz actual por la izquierda por la matriz de traslación: result = translate × current. postTranslate multiplica por la derecha: result = current × translate. La diferencia está en el orden de aplicación: las pre-operaciones se aplican antes de las transformaciones actuales, las post-operaciones después. Lo mismo aplica para preScale, postScale, preRotate, postRotate y preSkew, postSkew.
invert(Matrix inverse) calcula la matriz inversa. Si la matriz original es singular (determinante es cero), devuelve falso. concat(Matrix other) multiplica la matriz actual por la dada: set = set × other. Para el orden inverso, use setConcat(other, this).
mapRect(RectF rect) transforma un rectángulo y devuelve el resultado en un nuevo RectF. mapPoints(float[] dst, float[] src) transforma un array de puntos. mapVectors(float[] dst, float[] src) transforma vectores — sin considerar la traslación. mapRect es útil para calcular bounding boxes después de la transformación.
Matrix se utiliza activamente en dos escenarios clave de gráficos en Android: transformación de Canvas y transformación de Bitmap. En ambos casos, Matrix determina cómo se modificará la salida gráfica.
Canvas proporciona canvas.setMatrix(matrix) para el reemplazo completo de la matriz actual y canvas.concat(matrix) para multiplicar la transformación actual por la dada. Después de aplicar Matrix, todo el dibujo posterior — llamadas drawBitmap, drawRect, drawPath — se realiza en el sistema de coordenadas transformado. Canvas también mantiene su propia pila de estados guardados mediante save() y restore().
Bitmap.createBitmap(Bitmap source, int x, int y, int width, int height, Matrix matrix, boolean filter) crea un nuevo Bitmap con la transformación dada aplicada. Esta es una herramienta potente para crear copias escaladas, rotadas o distorsionadas de imágenes sin perder el Bitmap original. El parámetro filter controla el suavizado durante la interpolación de píxeles.
setPolyToPoly(float[] src, int srcIndex, float[] dst, int dstIndex, int pointCount) — una capacidad única de Matrix sin equivalente directo en CGAffineTransform. Calcula una matriz que transforma puntos dados de un polígono a otro. Con pointCount = 4, se crea una transformación de perspectiva (proyectiva) completa, permitiendo superponer Bitmap con distorsión de perspectiva.
Veamos ejemplos prácticos de uso de Matrix para transformación de gráficos en una aplicación Android con Kotlin.
El ejemplo crea un Matrix para una transformación combinada: traslación por (100, 50), escalado por 1.5x y rotación de 45 grados. El uso de postTranslate después de preRotate y preScale cambia el orden de aplicación de las operaciones.
val matrix = Matrix()
matrix.preScale(1.5f, 1.5f)
matrix.preRotate(45f)
matrix.postTranslate(100f, 50f)
// Aplicando a puntos
val pts = floatArrayOf(0f, 0f, 100f, 100f)
matrix.mapPoints(pts)
// Aplicando a rectángulo
val rect = RectF(0f, 0f, 200f, 100f)
matrix.mapRect(rect)
El ejemplo demuestra la aplicación de Matrix a Canvas en onDraw para rotar y escalar un círculo alrededor de su centro. Guardar y restaurar el estado de Canvas asegura que la transformación no afecte a los elementos de dibujo posteriores.
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
val cx = width / 2f
val cy = height / 2f
val radius = 100f
canvas.save()
val matrix = Matrix()
matrix.postTranslate(cx, cy)
matrix.postRotate(30f)
matrix.postScale(1.2f, 1.2f)
canvas.concat(matrix)
val paint = Paint().apply {
color = Color.BLUE
style = Paint.Style.FILL
}
canvas.drawCircle(0f, 0f, radius, paint)
canvas.restore()
}
El ejemplo usa setPolyToPoly para crear una distorsión de perspectiva de un Bitmap. Cuatro puntos de origen (esquinas del rectángulo original) se mapean a cuatro puntos destino que forman un trapezoide. El resultado es un efecto de imagen inclinada en el espacio.
fun applyPerspective(
bitmap: Bitmap,
skew: Float
): Bitmap {
val w = bitmap.width.toFloat()
val h = bitmap.height.toFloat()
val src = floatArrayOf(0f, 0f, w, 0f,
0f, h, w, h)
val dst = floatArrayOf(skew, 0f, w - skew, 0f,
0f, h, w, h)
val matrix = Matrix()
matrix.setPolyToPoly(src, 0, dst, 0, 4)
return Bitmap.createBitmap(
bitmap, 0, 0,
w.toInt(), h.toInt(),
matrix, true
)
}
Preguntas Frecuentes
Matrix trabaja con transformaciones afines y de perspectiva bidimensionales mediante una sola matriz 3×3. Camera (android.graphics.Camera) es una clase de más alto nivel que simula una cámara tridimensional: crea rotación 3D y luego proyecta el resultado en una Matrix 2D. Camera usa Matrix internamente.
Cree un Matrix con postRotate(90f) y páselo a Bitmap.createBitmap(original, 0, 0, w, h, matrix, true). Tenga en cuenta que al rotar 90 grados, el ancho y el alto del resultado se intercambian. Para rotación en un ángulo arbitrario, puede ser necesario recortar para evitar áreas vacías.
Use matrix.invert(resultMatrix). El método devuelve verdadero si la inversión es exitosa y escribe la matriz inversa en resultMatrix. La inversión puede ser imposible si la matriz es singular (por ejemplo, con escala cero). Siempre verifique el valor de retorno.
pre multiplica la nueva transformación por la izquierda: result = operation × current — la operación se aplica antes de las actuales. post multiplica por la derecha: result = current × operation — la operación se aplica después. Para una secuencia preRotate + postTranslate: primero rotación, luego traslación.
Sí, Matrix se usa en Jetpack Compose a través de la clase android.graphics.Matrix en interacción con Canvas Compose. En Compose, graphicsLayer está disponible para transformaciones (scale, rotationX, translationX y otras), pero para transformaciones complejas de Bitmap, se usa Matrix en código drawWithContent o drawBehind.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también