Matrix — это класс из Android SDK (android.graphics.Matrix), представляющий аффинное преобразование через матрицу 3×3. Он используется для трансформации графических объектов — перемещения, масштабирования, поворота и наклона. По данным Android Developers Documentation (2026), Matrix является основным инструментом для работы с трансформациями в Canvas, Bitmap и Drawable, обеспечивая точное управление координатами при кастомной отрисовке.
Главное
Matrix (android.graphics.Matrix) — это класс Android SDK, представляющий математическую матрицу 3×3, используемую для трансформации двумерных координат. Matrix является основным строительным блоком для всех графических преобразований в Android — от перемещения и масштабирования Canvas до сложных перспективных искажений Bitmap.
В отличие от iOS, где используются отдельные структуры CGAffineTransform (аффинные) и CATransform3D (3D), Android объединяет аффинные и перспективные преобразования в одном классе Matrix. Матрица 3×3 позволяет представлять как стандартные аффинные операции (последняя строка [0, 0, 1]), так и перспективные искажения, когда последняя строка содержит произвольные значения. Это даёт больше гибкости, но требует понимания математики матриц.
Matrix тесно интегрирован с Canvas API. Когда разработчик вызывает canvas.translate(), canvas.scale() или canvas.rotate(), эти методы внутренне модифицируют матрицу графического контекста. Получить текущую матрицу Canvas можно через canvas.getMatrix(), а вручную применить кастомную — через canvas.setMatrix() или canvas.concat().
Matrix поддерживает четыре базовых типа аффинных преобразований: translate, scale, rotate, skew (наклон). Каждый тип имеет метод для пре-умножения (pre), пост-умножения (post) и установки (set). Разница между preTranslate и postTranslate — в порядке умножения матриц, что влияет на итоговое преобразование при комбинировании.
| Операция | Метод | Параметры | Описание |
|---|---|---|---|
| Translate | setTranslate / preTranslate / postTranslate | dx, dy | Смещение по осям X и Y |
| Scale | setScale / preScale / postScale | sx, sy, px, py | Масштабирование с опорной точкой |
| Rotate | setRotate / preRotate / postRotate | degrees, px, py | Поворот вокруг опорной точки |
| Skew | setSkew / preSkew / postSkew | kx, ky | Наклон (сдвиг) вдоль осей |
Translate изменяет положение всех точек на заданное смещение dx, dy. Положительный dx сдвигает вправо, dy — вниз (в системе координат экрана Android ось Y направлена вниз). translate не изменяет форму объекта — только его позицию. Это самая простая и часто используемая операция для позиционирования элементов.
Scale изменяет размер объекта с коэффициентами sx (по X) и sy (по Y). Параметры px, py задают опорную точку масштабирования (pivot point). Если px, py не указаны, масштабирование выполняется относительно начала координат (0, 0). При sx = sy объект масштабируется равномерно. Отрицательные значения создают отражение.
Rotate вращает объект на заданный угол (в градусах) вокруг опорной точки (px, py). Положительное значение градусов соответствует повороту по часовой стрелке (в отличие от iOS/macOS, где положительный угол — против часовой). Если px, py не заданы, поворот выполняется вокруг начала координат.
Skew (сдвиг) деформирует объект, наклоняя его вдоль оси X (kx) или оси Y (ky). Значение 1.0 наклоняет на 45 градусов. Skew используется для создания эффектов наклона, имитации трёхмерного вида (псевдо-3D) и искажения перспективы.
Matrix хранит элементы матрицы 3×3 во внутреннем массиве из 9 значений с плавающей точкой (float[9]). Порядок хранения — column-major (по столбцам), что соответствует стандартному математическому представлению. Доступ к отдельным элементам осуществляется через константы: Matrix.MSCALE_X, Matrix.MSKEW_Y, Matrix.MTRANS_X и так далее.
Матрица организована следующим образом: первые два столбца (MSACALE_X, MSKEW_X, MSKEW_Y, MSCALE_Y) отвечают за масштабирование, поворот и наклон. Третий столбец (MTRANS_X, MTRANS_Y, MPERSP_2) — за перемещение и перспективу. Для аффинного преобразования MPERSP_0 и MPERSP_1 равны 0, а MPERSP_2 равен 1.
Для получения значений матрицы используется getValues(float[] values), который заполняет массив из 9 элементов. Для установки — setValues(float[] values). Это позволяет манипулировать матрицей напрямую для сложных пользовательских преобразований, выходящих за рамки стандартных методов translate, scale, rotate и skew.
Matrix предоставляет несколько методов для классификации текущего состояния. isIdentity() проверяет, является ли матрица единичной. isAffine() — содержит ли только аффинные преобразования (MPERSP_0 = 0, MPERSP_1 = 0, MPERSP_2 = 1). Эти проверки полезны для оптимизации: если матрица единичная, трансформацию можно пропустить.
Matrix поддерживает несколько категорий операций: установка (set), пре-умножение (pre), пост-умножение (post), конкатенация (concat), инверсия (invert) и маппинг (map). Каждая категория решает свою задачу при построении сложных преобразований.
preTranslate умножает текущую матрицу слева на матрицу сдвига: result = translate × current. postTranslate умножает справа: result = current × translate. Разница в порядке применения: pre-операции применяются до текущих трансформаций, post-операции — после. Аналогично работают preScale, postScale, preRotate, postRotate и preSkew, postSkew.
invert(Matrix inverse) вычисляет обратную матрицу. Если исходная матрица вырождена (определитель равен нулю), возвращается false. concat(Matrix other) умножает текущую матрицу на переданную: set = set × other. Для обратного порядка используйте setConcat(other, this).
mapRect(RectF rect) трансформирует прямоугольник и возвращает результат в новый RectF. mapPoints(float[] dst, float[] src) трансформирует массив точек. mapVectors(float[] dst, float[] src) трансформирует векторы — без учёта смещения (translate). mapRect полезен для вычисления bounding box после трансформации.
Matrix активно используется в двух ключевых сценариях Android-графики: трансформация Canvas и трансформация Bitmap. В обоих случаях Matrix определяет, как именно будет изменён графический вывод.
Canvas предоставляет методы canvas.setMatrix(matrix) для полной замены текущей матрицы и canvas.concat(matrix) для умножения текущего преобразования на переданное. После применения Matrix вся последующая отрисовка — вызовы drawBitmap, drawRect, drawPath — выполняется в трансформированной системе координат. Canvas также хранит собственный стек сохранённых состояний через save() и restore().
Bitmap.createBitmap(Bitmap source, int x, int y, int width, int height, Matrix matrix, boolean filter) создаёт новый Bitmap с применением заданного преобразования. Это мощный инструмент для создания масштабированных, повёрнутых или искажённых копий изображений без потери исходного Bitmap. Параметр filter управляет сглаживанием при интерполяции пикселей.
setPolyToPoly(float[] src, int srcIndex, float[] dst, int dstIndex, int pointCount) — уникальная возможность Matrix, не имеющая прямых аналогов в CGAffineTransform. Она вычисляет матрицу, преобразующую заданные точки из одного многоугольника в другой. При pointCount = 4 создаётся полноценное перспективное (projective) преобразование, позволяющее накладывать Bitmap с искажением перспективы.
Рассмотрим практические примеры использования Matrix для трансформации графики в Android-приложении на Kotlin.
Пример создаёт Matrix для комбинированного преобразования: смещение на (100, 50), масштабирование в 1.5 раза и поворот на 45 градусов. Использование postTranslate после preRotate и preScale меняет порядок применения операций.
val matrix = Matrix()
matrix.preScale(1.5f, 1.5f)
matrix.preRotate(45f)
matrix.postTranslate(100f, 50f)
// Applying to points
val pts = floatArrayOf(0f, 0f, 100f, 100f)
matrix.mapPoints(pts)
// Applying to rectangle
val rect = RectF(0f, 0f, 200f, 100f)
matrix.mapRect(rect)
Пример демонстрирует применение Matrix к Canvas в onDraw для поворота и масштабирования круга вокруг его центра. Сохранение и восстановление состояния Canvas гарантирует, что трансформация не повлияет на последующие элементы отрисовки.
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()
}
Пример использует setPolyToPoly для создания перспективного искажения Bitmap. Четыре исходные точки (углы исходного прямоугольника) маппятся на четыре целевых точки, образующих трапецию. Результат — эффект наклонённой в пространстве картинки.
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
)
}
Часто задаваемые вопросы
Matrix работает с двумерными аффинными и перспективными преобразованиями через одну матрицу 3×3. Camera (android.graphics.Camera) — это более высокоуровневый класс, имитирующий трёхмерную камеру: он создаёт 3D-вращение и затем проецирует результат в 2D Matrix. Camera использует Matrix внутри себя.
Создайте Matrix с postRotate(90f) и передайте в Bitmap.createBitmap(original, 0, 0, w, h, matrix, true). Учтите, что при повороте на 90 градусов ширина и высота результата меняются местами. Для поворота на произвольный угол может потребоваться обрезка, чтобы избежать пустых областей.
Используйте matrix.invert(resultMatrix). Метод возвращает true, если инверсия успешна, и записывает обратную матрицу в resultMatrix. Инверсия может быть невозможна, если матрица вырождена (например, при нулевом масштабе). Всегда проверяйте возвращаемое значение.
pre умножает новое преобразование слева: result = operation × current — операция применяется до текущих. post умножает справа: result = current × operation — операция применяется после. Для последовательности preRotate + postTranslate: сначала поворот, потом смещение.
Да, Matrix используется в Jetpack Compose через класс android.graphics.Matrix в взаимодействии с Canvas Compose. В Compose доступны graphicsLayer для трансформации (scale, rotationX, translationX и другие), но для сложных преобразований Bitmap применяется Matrix в коде drawWithContent или drawBehind.
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также