Matrix — کلاسی از Android SDK (android.graphics.Matrix) است که تبدیل وابسته (affine) را از طریق یک ماتریس 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 (سه بعدی) استفاده میشود، 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 برای ایجاد اثرات کج شدن، شبیهسازی نمای سه بعدی (pseudo-3D) و تغییر شکل پرسپکتیو استفاده میشود.
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) بردارها را بدون در نظر گرفتن جابهجایی (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)
// اعمال به نقاط
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 ایجاد میکند و سپس نتیجه را به Matrix 2D投影 میکند. 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 از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید