Matrix در Android: چیست، انواع ماتریس و کار با تبدیل‌ها

نویسنده: IT Sectr منتشر شده: 2026-07-22 زمان مطالعه: 9 دقیقه

Matrix — کلاسی از Android SDK (android.graphics.Matrix) است که تبدیل وابسته (affine) را از طریق یک ماتریس 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 (سه بعدی) استفاده می‌شود، 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 برای ایجاد اثرات کج شدن، شبیه‌سازی نمای سه بعدی (pseudo-3D) و تغییر شکل پرسپکتیو استفاده می‌شود.

ساختار ماتریس 3×3

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

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)

// اعمال به نقاط
val pts = floatArrayOf(0f, 0f, 100f, 100f)
matrix.mapPoints(pts)

// اعمال به مستطیل
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 ایجاد می‌کند و سپس نتیجه را به Matrix 2D投影 می‌کند. 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 از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید