Matrix в Android: что это, типы матриц и работа с преобразованиями

Автор: IT Sectr Опубликовано: 2026-07-22 Время чтения: 9 мин

Matrix — это класс из Android SDK (android.graphics.Matrix), представляющий аффинное преобразование через матрицу 3×3. Он используется для трансформации графических объектов — перемещения, масштабирования, поворота и наклона. По данным Android Developers Documentation (2026), Matrix является основным инструментом для работы с трансформациями в Canvas, Bitmap и Drawable, обеспечивая точное управление координатами при кастомной отрисовке.

Главное

  • Matrix — класс Android для аффинных и перспективных преобразований с матрицей 3×3
  • Аффинные операции: translate (сдвиг), scale (масштаб), rotate (поворот) и skew (наклон)
  • Matrix поддерживает перспективные (projective) преобразования через setPolyToPoly
  • Порядок применения операций важен — Matrix.concat выполняет последовательное умножение
  • Matrix применяется к Canvas, Bitmap, RectF, PointF и Path в Android-графике

Что такое Matrix в Android?

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

Matrix поддерживает четыре базовых типа аффинных преобразований: translate, scale, rotate, skew (наклон). Каждый тип имеет метод для пре-умножения (pre), пост-умножения (post) и установки (set). Разница между preTranslate и postTranslate — в порядке умножения матриц, что влияет на итоговое преобразование при комбинировании.

ОперацияМетодПараметрыОписание
TranslatesetTranslate / preTranslate / postTranslatedx, dyСмещение по осям X и Y
ScalesetScale / preScale / postScalesx, sy, px, pyМасштабирование с опорной точкой
RotatesetRotate / preRotate / postRotatedegrees, px, pyПоворот вокруг опорной точки
SkewsetSkew / preSkew / postSkewkx, kyНаклон (сдвиг) вдоль осей

Translate — перемещение

Translate изменяет положение всех точек на заданное смещение dx, dy. Положительный dx сдвигает вправо, dy — вниз (в системе координат экрана Android ось Y направлена вниз). translate не изменяет форму объекта — только его позицию. Это самая простая и часто используемая операция для позиционирования элементов.

Scale — масштабирование

Scale изменяет размер объекта с коэффициентами sx (по X) и sy (по Y). Параметры px, py задают опорную точку масштабирования (pivot point). Если px, py не указаны, масштабирование выполняется относительно начала координат (0, 0). При sx = sy объект масштабируется равномерно. Отрицательные значения создают отражение.

Rotate — поворот

Rotate вращает объект на заданный угол (в градусах) вокруг опорной точки (px, py). Положительное значение градусов соответствует повороту по часовой стрелке (в отличие от iOS/macOS, где положительный угол — против часовой). Если px, py не заданы, поворот выполняется вокруг начала координат.

Skew — наклон

Skew (сдвиг) деформирует объект, наклоняя его вдоль оси X (kx) или оси Y (ky). Значение 1.0 наклоняет на 45 градусов. Skew используется для создания эффектов наклона, имитации трёхмерного вида (псевдо-3D) и искажения перспективы.

Сруктура матрицы 3×3

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

Matrix поддерживает несколько категорий операций: установка (set), пре-умножение (pre), пост-умножение (post), конкатенация (concat), инверсия (invert) и маппинг (map). Каждая категория решает свою задачу при построении сложных преобразований.

Pre и Post операции

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).

Map — применение к точкам и прямоугольникам

mapRect(RectF rect) трансформирует прямоугольник и возвращает результат в новый RectF. mapPoints(float[] dst, float[] src) трансформирует массив точек. mapVectors(float[] dst, float[] src) трансформирует векторы — без учёта смещения (translate). mapRect полезен для вычисления bounding box после трансформации.

Применение в Canvas и Bitmap

Matrix активно используется в двух ключевых сценариях Android-графики: трансформация Canvas и трансформация Bitmap. В обоих случаях Matrix определяет, как именно будет изменён графический вывод.

Canvas трансформация через Matrix

Canvas предоставляет методы canvas.setMatrix(matrix) для полной замены текущей матрицы и canvas.concat(matrix) для умножения текущего преобразования на переданное. После применения Matrix вся последующая отрисовка — вызовы drawBitmap, drawRect, drawPath — выполняется в трансформированной системе координат. Canvas также хранит собственный стек сохранённых состояний через save() и restore().

Bitmap трансформация через Matrix

Bitmap.createBitmap(Bitmap source, int x, int y, int width, int height, Matrix matrix, boolean filter) создаёт новый Bitmap с применением заданного преобразования. Это мощный инструмент для создания масштабированных, повёрнутых или искажённых копий изображений без потери исходного Bitmap. Параметр filter управляет сглаживанием при интерполяции пикселей.

setPolyToPoly — перспективные преобразования

setPolyToPoly(float[] src, int srcIndex, float[] dst, int dstIndex, int pointCount) — уникальная возможность Matrix, не имеющая прямых аналогов в CGAffineTransform. Она вычисляет матрицу, преобразующую заданные точки из одного многоугольника в другой. При pointCount = 4 создаётся полноценное перспективное (projective) преобразование, позволяющее накладывать Bitmap с искажением перспективы.

Примеры кода на Kotlin

Рассмотрим практические примеры использования Matrix для трансформации графики в Android-приложении на Kotlin.

Базовые аффинные преобразования

Пример создаёт Matrix для комбинированного преобразования: смещение на (100, 50), масштабирование в 1.5 раза и поворот на 45 градусов. Использование postTranslate после preRotate и preScale меняет порядок применения операций.

kotlin
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)

Canvas трансформация с save и restore

Пример демонстрирует применение Matrix к Canvas в onDraw для поворота и масштабирования круга вокруг его центра. Сохранение и восстановление состояния Canvas гарантирует, что трансформация не повлияет на последующие элементы отрисовки.

kotlin
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

Пример использует setPolyToPoly для создания перспективного искажения Bitmap. Четыре исходные точки (углы исходного прямоугольника) маппятся на четыре целевых точки, образующих трапецию. Результат — эффект наклонённой в пространстве картинки.

kotlin
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 от Camera в Android?

Matrix работает с двумерными аффинными и перспективными преобразованиями через одну матрицу 3×3. Camera (android.graphics.Camera) — это более высокоуровневый класс, имитирующий трёхмерную камеру: он создаёт 3D-вращение и затем проецирует результат в 2D Matrix. Camera использует Matrix внутри себя.

Как повернуть Bitmap на 90 градусов?

Создайте Matrix с postRotate(90f) и передайте в Bitmap.createBitmap(original, 0, 0, w, h, matrix, true). Учтите, что при повороте на 90 градусов ширина и высота результата меняются местами. Для поворота на произвольный угол может потребоваться обрезка, чтобы избежать пустых областей.

Как получить обратное преобразование Matrix?

Используйте matrix.invert(resultMatrix). Метод возвращает true, если инверсия успешна, и записывает обратную матрицу в resultMatrix. Инверсия может быть невозможна, если матрица вырождена (например, при нулевом масштабе). Всегда проверяйте возвращаемое значение.

В чём разница между pre и post операциями?

pre умножает новое преобразование слева: result = operation × current — операция применяется до текущих. post умножает справа: result = current × operation — операция применяется после. Для последовательности preRotate + postTranslate: сначала поворот, потом смещение.

Можно ли использовать Matrix в Compose?

Да, Matrix используется в Jetpack Compose через класс android.graphics.Matrix в взаимодействии с Canvas Compose. В Compose доступны graphicsLayer для трансформации (scale, rotationX, translationX и другие), но для сложных преобразований Bitmap применяется Matrix в коде drawWithContent или drawBehind.

Итоги

  • Matrix — класс Android для аффинных и перспективных преобразований с матрицей 3×3
  • Четыре базовых типа: translate (сдвиг), scale (масштаб), rotate (поворот), skew (наклон)
  • pre/post операции управляют порядком применения: pre — до текущих, post — после текущих преобразований
  • setPolyToPoly — уникальная функция для вычисления перспективного преобразования по 4 парам точек
  • Matrix применяется к Canvas через concat, к Bitmap через createBitmap с Matrix, к точкам через mapPoints
  • invert вычисляет обратное преобразование, возвращая false для вырожденных матриц
  • isAffine и isIdentity помогают классифицировать состояние матрицы для оптимизации

Мы разработаем мобильное приложение под ключ

IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

Читайте также