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 задають опорну точку масштабування. Якщо px, py не вказані, масштабування виконується відносно початку координат (0, 0). При sx = sy об’єкт масштабується рівномірно. Від’ємні значення створюють відображення.
Rotate повертає об’єкт на заданий кут (у градусах) навколо опорної точки (px, py). Позитивне значення градусів відповідає повороту за годинниковою стрілкою (на відміну від iOS/macOS, де позитивний кут — проти годинникової стрілки). Якщо px, py не задані, поворот виконується навколо початку координат.
Skew (зсув) деформує об’єкт, нахиляючи його вздовж осі X (kx) або Y (ky). Значення 1.0 нахиляє на 45 градусів. Skew використовується для створення ефектів нахилу, імітації тривимірного вигляду та спотворення перспективи.
Matrix зберігає елементи матриці 3×3 у внутрішньому масиві з 9 значень з плаваючою крапкою (float[9]). Порядок зберігання — column-major (за стовпцями), що відповідає стандартному математичному поданню. Доступ до окремих елементів здійснюється через константи: Matrix.MSCALE_X, Matrix.MSKEW_Y, Matrix.MTRANS_X і так далі.
Матриця організована наступним чином: перші два стовпці (MSCALE_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) трансформує вектори — без урахування зсуву. mapRect корисний для обчислення межевого контейнера після трансформації.
Matrix активно використовується в двох ключових сценаріях андроїдної графіки: трансформація 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 створюється повноцінне перспективне (проєктивне) перетворення, що дозволяє накладати Bitmap із спотворенням перспективи.
Розглянемо практичні приклади використання Matrix для трансформації графіки в андроїд додатку на 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)
// Застосування до точок
val pts = floatArrayOf(0f, 0f, 100f, 100f)
matrix.mapPoints(pts)
// Застосування до прямокутника
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 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також