Matrix — uma classe do SDK Android (android.graphics.Matrix) que representa uma transformação afim através de uma matriz 3×3. É usada para transformar objetos gráficos — mover, escalar, rotacionar e inclinar. De acordo com a Documentação para Desenvolvedores Android (2026), Matrix é a principal ferramenta para trabalhar com transformações em Canvas, Bitmap e Drawable, fornecendo controle preciso de coordenadas na renderização personalizada.
Pontos-Chave
Matrix (android.graphics.Matrix) — uma classe do SDK Android que representa uma matriz matemática 3×3 usada para transformar coordenadas bidimensionais. Matrix é o bloco de construção fundamental para todas as transformações gráficas no Android — desde movimento e dimensionamento de Canvas até distorções complexas de perspectiva de Bitmap.
Ao contrário do iOS, que usa estruturas separadas CGAffineTransform (afim) e CATransform3D (3D), o Android combina transformações afins e de perspectiva em uma única classe Matrix. A matriz 3×3 permite representar tanto operações afins padrão (última linha [0, 0, 1]) quanto distorções de perspectiva onde a última linha contém valores arbitrários. Isso oferece mais flexibilidade, mas requer compreensão da matemática matricial.
Matrix está intimamente integrada à API Canvas. Quando um desenvolvedor chama canvas.translate(), canvas.scale() ou canvas.rotate(), esses métodos modificam internamente a matriz do contexto gráfico. Você pode obter a matriz atual do Canvas via canvas.getMatrix() e aplicar manualmente uma personalizada com canvas.setMatrix() ou canvas.concat().
Matrix suporta quatro tipos básicos de transformações afins: translate, scale, rotate, skew (inclinar). Cada tipo possui métodos para pré-multiplicação (pre), pós-multiplicação (post) e definição (set). A diferença entre preTranslate e postTranslate está na ordem da multiplicação de matrizes, o que afeta a transformação final ao combinar operações.
| Operação | Método | Parâmetros | Descrição |
|---|---|---|---|
| Mover | setTranslate / preTranslate / postTranslate | dx, dy | Deslocamento nos eixos X e Y |
| Escalar | setScale / preScale / postScale | sx, sy, px, py | Escalonamento com ponto de pivô |
| Rotacionar | setRotate / preRotate / postRotate | degrees, px, py | Rotação em torno do ponto de pivô |
| Inclinar | setSkew / preSkew / postSkew | kx, ky | Inclinação (cisalhamento) ao longo dos eixos |
Translate altera a posição de todos os pontos por um deslocamento dx, dy. Dx positivo move para a direita, dy — para baixo (no sistema de coordenadas de tela do Android, o eixo Y aponta para baixo). Translate não altera a forma do objeto — apenas sua posição. É a operação mais simples e mais usada para posicionar elementos.
Scale altera o tamanho de um objeto com fatores sx (ao longo de X) e sy (ao longo de Y). Os parâmetros px, py especificam o ponto de pivô para o escalonamento. Se px, py não forem especificados, o escalonamento é realizado em relação à origem (0, 0). Quando sx = sy, o objeto escala uniformemente. Valores negativos criam um reflexo.
Rotate gira um objeto por um ângulo dado (em graus) em torno de um ponto de pivô (px, py). Graus positivos correspondem à rotação no sentido horário (ao contrário do iOS/macOS, onde um ângulo positivo é anti-horário). Se px, py não forem definidos, a rotação é realizada em torno da origem.
Skew (cisalhamento) deforma um objeto inclinando-o ao longo do eixo X (kx) ou do eixo Y (ky). Um valor de 1.0 inclina 45 graus. Skew é usado para criar efeitos de inclinação, aparências pseudo-3D e distorção de perspectiva.
Matrix armazena seus elementos 3×3 em um array interno de 9 valores de ponto flutuante (float[9]). A ordem de armazenamento é column-major (por colunas), consistente com a representação matemática padrão. O acesso a elementos individuais é feito através de constantes: Matrix.MSCALE_X, Matrix.MSKEW_Y, Matrix.MTRANS_X e assim por diante.
A matriz é organizada da seguinte forma: as duas primeiras colunas (MSCALE_X, MSKEW_X, MSKEW_Y, MSCALE_Y) lidam com dimensionamento, rotação e inclinação. A terceira coluna (MTRANS_X, MTRANS_Y, MPERSP_2) lida com translação e perspectiva. Para transformações afins, MPERSP_0 e MPERSP_1 são 0, e MPERSP_2 é 1.
Para obter valores da matriz, use getValues(float[] values), que preenche um array de 9 elementos. Para defini-los, use setValues(float[] values). Isso permite a manipulação direta da matriz para transformações personalizadas complexas além dos métodos padrão translate, scale, rotate e skew.
Matrix fornece vários métodos para classificar o estado atual. isIdentity() verifica se a matriz é identidade. isAffine() verifica se contém apenas transformações afins (MPERSP_0 = 0, MPERSP_1 = 0, MPERSP_2 = 1). Essas verificações são úteis para otimização: se a matriz for identidade, a transformação pode ser ignorada.
Matrix suporta várias categorias de operações: definição (set), pré-multiplicação (pre), pós-multiplicação (post), concatenação (concat), inversão (invert) e mapeamento (map). Cada categoria tem seu propósito ao construir transformações complexas.
preTranslate multiplica a matriz atual à esquerda pela matriz de translação: result = translate × current. postTranslate multiplica à direita: result = current × translate. A diferença está na ordem de aplicação: operações pre são aplicadas antes das transformações atuais, operações post depois. O mesmo se aplica a preScale, postScale, preRotate, postRotate e preSkew, postSkew.
invert(Matrix inverse) calcula a matriz inversa. Se a matriz original for singular (determinante é zero), retorna falso. concat(Matrix other) multiplica a matriz atual pela fornecida: set = set × other. Para a ordem inversa, use setConcat(other, this).
mapRect(RectF rect) transforma um retângulo e retorna o resultado em um novo RectF. mapPoints(float[] dst, float[] src) transforma um array de pontos. mapVectors(float[] dst, float[] src) transforma vetores — sem considerar a translação. mapRect é útil para calcular bounding boxes após a transformação.
Matrix é ativamente usada em dois cenários principais de gráficos Android: transformação de Canvas e transformação de Bitmap. Em ambos os casos, Matrix determina como a saída gráfica será modificada.
Canvas fornece canvas.setMatrix(matrix) para substituição completa da matriz atual e canvas.concat(matrix) para multiplicar a transformação atual pela fornecida. Após aplicar Matrix, toda a renderização subsequente — chamadas drawBitmap, drawRect, drawPath — é realizada no sistema de coordenadas transformado. Canvas também mantém sua própria pilha de estados salvos via save() e restore().
Bitmap.createBitmap(Bitmap source, int x, int y, int width, int height, Matrix matrix, boolean filter) cria um novo Bitmap com a transformação fornecida aplicada. Esta é uma ferramenta poderosa para criar cópias dimensionadas, rotacionadas ou distorcidas de imagens sem perder o Bitmap original. O parâmetro filter controla o anti-aliasing durante a interpolação de pixels.
setPolyToPoly(float[] src, int srcIndex, float[] dst, int dstIndex, int pointCount) — uma capacidade única de Matrix sem equivalente direto em CGAffineTransform. Ela calcula uma matriz que transforma pontos dados de um polígono para outro. Com pointCount = 4, uma transformação de perspectiva (projetiva) completa é criada, permitindo sobrepor Bitmap com distorção de perspectiva.
Vejamos exemplos práticos de uso de Matrix para transformação de gráficos em um aplicativo Android com Kotlin.
O exemplo cria um Matrix para uma transformação combinada: translação por (100, 50), dimensionamento por 1.5x e rotação de 45 graus. O uso de postTranslate após preRotate e preScale altera a ordem de aplicação das operações.
val matrix = Matrix()
matrix.preScale(1.5f, 1.5f)
matrix.preRotate(45f)
matrix.postTranslate(100f, 50f)
// Aplicando a pontos
val pts = floatArrayOf(0f, 0f, 100f, 100f)
matrix.mapPoints(pts)
// Aplicando a retângulo
val rect = RectF(0f, 0f, 200f, 100f)
matrix.mapRect(rect)
O exemplo demonstra a aplicação de Matrix ao Canvas em onDraw para rotacionar e dimensionar um círculo em torno de seu centro. Salvar e restaurar o estado do Canvas garante que a transformação não afete os elementos de renderização subsequentes.
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()
}
O exemplo usa setPolyToPoly para criar uma distorção de perspectiva de um Bitmap. Quatro pontos de origem (cantos do retângulo original) são mapeados para quatro pontos de destino formando um trapézio. O resultado é um efeito de imagem inclinada no espaço.
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
)
}
Perguntas Frequentes
Matrix trabalha com transformações afins e de perspectiva bidimensionais através de uma única matriz 3×3. Camera (android.graphics.Camera) é uma classe de nível mais alto que simula uma câmera tridimensional: ela cria rotação 3D e então projeta o resultado em uma Matrix 2D. Camera usa Matrix internamente.
Crie um Matrix com postRotate(90f) e passe para Bitmap.createBitmap(original, 0, 0, w, h, matrix, true). Note que ao rotacionar 90 graus, a largura e altura do resultado se invertem. Para rotação em ângulo arbitrário, pode ser necessário recortar para evitar áreas vazias.
Use matrix.invert(resultMatrix). O método retorna verdadeiro se a inversão for bem-sucedida e escreve a matriz inversa em resultMatrix. A inversão pode ser impossível se a matriz for singular (por exemplo, com escala zero). Sempre verifique o valor de retorno.
pre multiplica a nova transformação à esquerda: result = operation × current — a operação é aplicada antes das atuais. post multiplica à direita: result = current × operation — a operação é aplicada depois. Para uma sequência preRotate + postTranslate: primeiro rotação, depois translação.
Sim, Matrix é usada no Jetpack Compose através da classe android.graphics.Matrix em interação com o Canvas Compose. No Compose, graphicsLayer está disponível para transformações (scale, rotationX, translationX e outras), mas para transformações complexas de Bitmap, Matrix é usada em código drawWithContent ou drawBehind.
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também