ماتريكس في أندرويد: ما هي، أنواع المصفوفات والعمل مع التحويلات

المؤلف: IT Sectr نُشر: 2026-07-22 وقت القراءة: 9 دق

ماتريكس — هي فئة من Android SDK (android.graphics.Matrix) تمثل تحويلاً أفينياً عبر مصفوفة 3×3. تُستخدم لتحويل الكائنات الرسومية — النقل والقياس والتدوير والإمالة. وفقاً لوثائق مطوري أندرويد (2026)، تُعد ماتريكس الأداة الرئيسية للعمل مع التحويلات في Canvas وBitmap وDrawable، مما يوفر تحكماً دقيقاً في الإحداثيات عند الرسم المخصص.

النقاط الرئيسية

  • ماتريكس — فئة أندرويد للتحويلات الأفينية والمنظورية بمصفوفة 3×3
  • العمليات الأفينية: translate (نقل)، scale (قياس)، rotate (تدوير) وskew (إمالة)
  • ماتريكس تدعم التحويلات الإسقاطية عبر setPolyToPoly
  • ترتيب تطبيق العمليات مهم — Matrix.concat يقوم بالضرب التسلسلي
  • تُطبق ماتريكس على Canvas وBitmap وRectF وPointF وPath في رسومات أندرويد

ما هي ماتريكس في أندرويد؟

ماتريكس (android.graphics.Matrix) — هي فئة من Android SDK تمثل مصفوفة رياضية 3×3 تُستخدم لتحويل الإحداثيات ثنائية الأبعاد. تُعد ماتريكس اللبنة الأساسية لجميع التحويلات الرسومية في أندرويد — من تحريك Canvas وتغيير حجمه إلى التشوهات المنظورية المعقدة لـ Bitmap.

على عكس iOS، الذي يستخدم هياكل منفصلة CGAffineTransform (أفيني) وCATransform3D (ثلاثي الأبعاد)، يجمع أندرويد بين التحويلات الأفينية والمنظورية في فئة واحدة ماتريكس. تسمح المصفوفة 3×3 بتمثيل كل من العمليات الأفينية القياسية (الصف الأخير [0, 0, 1]) والتشوهات المنظورية عندما يحتوي الصف الأخير على قيم عشوائية. هذا يوفر مرونة أكبر ولكنه يتطلب فهم رياضيات المصفوفات.

ماتريكس مدمجة بإحكام مع واجهة Canvas API. عندما يستدعي المطور canvas.translate() أو canvas.scale() أو canvas.rotate()، تقوم هذه الطرق بتعديل مصفوفة السياق الرسومي داخلياً. يمكنك الحصول على مصفوفة Canvas الحالية عبر canvas.getMatrix() وتطبيق مصفوفة مخصصة يدوياً عبر canvas.setMatrix() أو canvas.concat().

أنواع تحويلات ماتريكس

ماتريكس تدعم أربعة أنواع أساسية من التحويلات الأفينية: translate، scale، rotate، skew (إمالة). لكل نوع طرق للضرب المسبق (pre) والضرب اللاحق (post) والتعيين (set). الفرق بين preTranslate وpostTranslate يكمن في ترتيب ضرب المصفوفات، مما يؤثر على التحويل النهائي عند دمج العمليات.

العمليةالطريقةالمعلماتالوصف
نقلsetTranslate / preTranslate / postTranslatedx, dyالإزاحة على طول المحورين X وY
قياسsetScale / preScale / postScalesx, sy, px, pyالقياس مع نقطة ارتكاز
تدويرsetRotate / preRotate / postRotatedegrees, px, pyالتدوير حول نقطة ارتكاز
إمالةsetSkew / preSkew / postSkewkx, kyالإمالة (القص) على طول المحاور

النقل — التحرك

Translate يغير موضع جميع النقاط بإزاحة معينة dx, dy. dx موجب يحرك لليمين، dy — للأسفل (في نظام إحداثيات شاشة أندرويد، المحور 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 لإنشاء تأثيرات الإمالة والمظهر شبه ثلاثي الأبعاد وتشويه المنظور.

هيكل المصفوفة 3×3

ماتريكس تخزن عناصرها 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.

التحقق من نوع المصفوفة

ماتريكس توفر عدة طرق لتصنيف الحالة الحالية. isIdentity() يتحقق مما إذا كانت المصفوفة مصفوفة وحدة. isAffine() يتحقق مما إذا كانت تحتوي فقط على تحويلات أفينية (MPERSP_0 = 0, MPERSP_1 = 0, MPERSP_2 = 1). هذه الفحوصات مفيدة للتحسين: إذا كانت المصفوفة مصفوفة وحدة، يمكن تخطي التحويل.

العمليات الأساسية مع ماتريكس

ماتريكس تدعم عدة فئات من العمليات: التعيين (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) يحول المتجهات — دون مراعاة النقل. mapRect مفيد لحساب المربعات المحيطة (bounding boxes) بعد التحويل.

التطبيق في Canvas وBitmap

ماتريكس تُستخدم بنشاط في سيناريوهين رئيسيين لرسومات أندرويد: تحويل Canvas وتحويل Bitmap. في كلتا الحالتين، تحدد ماتريكس كيفية تعديل المخرجات الرسومية.

تحويل Canvas عبر ماتريكس

Canvas يوفر canvas.setMatrix(matrix) للاستبدال الكامل للمصفوفة الحالية وcanvas.concat(matrix) لضرب التحويل الحالي بالمعطى. بعد تطبيق ماتريكس، كل الرسم اللاحق — استدعاءات drawBitmap وdrawRect وdrawPath — يتم في نظام الإحداثيات المحول. Canvas يحتفظ أيضاً بمكدس الحالات المحفوظة الخاص به عبر save() وrestore().

تحويل Bitmap عبر ماتريكس

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) — قدرة فريدة لماتريكس ليس لها مقابل مباشر في CGAffineTransform. تحسب مصفوفة تحول نقاطاً معينة من مضلع إلى آخر. مع pointCount = 4، يتم إنشاء تحويل منظور (إسقاطي) كامل، مما يسمح بتراكب Bitmap مع تشويه منظور.

أمثلة كود بلغة Kotlin

لنلقِ نظرة على أمثلة عملية لاستخدام ماتريكس لتحويل الرسومات في تطبيق أندرويد بلغة Kotlin.

التحويلات الأفينية الأساسية

المثال ينشئ ماتريكس لتحويل مدمج: نقل بمقدار (100, 50)، قياس بمقدار 1.5x وتدوير بزاوية 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

المثال يوضح تطبيق ماتريكس على 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
    )
}

الأسئلة الشائعة

ما الفرق بين ماتريكس وكاميرا في أندرويد؟

ماتريكس تعمل مع التحويلات الأفينية والمنظورية ثنائية الأبعاد من خلال مصفوفة واحدة 3×3. الكاميرا (android.graphics.Camera) هي فئة عالية المستوى تحاكي كاميرا ثلاثية الأبعاد: تنشئ دوراناً ثلاثي الأبعاد ثم تسقط النتيجة في ماتريكس ثنائية الأبعاد. الكاميرا تستخدم ماتريكس داخلياً.

كيفية تدوير Bitmap بمقدار 90 درجة؟

أنشئ ماتريكس مع postRotate(90f) ومرره إلى Bitmap.createBitmap(original, 0, 0, w, h, matrix, true). لاحظ أنه عند التدوير بمقدار 90 درجة، فإن عرض وارتفاع النتيجة يتبادلان. للتدوير بزاوية عشوائية، قد يكون الاقتصاص ضرورياً لتجنب المناطق الفارغة.

كيفية الحصول على التحويل العكسي لماتريكس؟

استخدم matrix.invert(resultMatrix). يعيد الأسلوب true إذا كان الانعكاس ناجحاً ويكتب المصفوفة العكسية في resultMatrix. قد يكون الانعكاس مستحيلاً إذا كانت المصفوفة شاذة (مثلاً، عند قياس صفري). تحقق دائماً من القيمة المعادة.

ما الفرق بين عمليات pre وpost؟

pre تضرب التحويل الجديد من اليسار: result = operation × current — تُطبق العملية قبل التحويلات الحالية. post تضرب من اليمين: result = current × operation — تُطبق العملية بعدها. لتسلسل preRotate + postTranslate: أولاً التدوير، ثم النقل.

هل يمكن استخدام ماتريكس في Compose؟

نعم، تُستخدم ماتريكس في Jetpack Compose من خلال فئة android.graphics.Matrix في التفاعل مع Canvas Compose. في Compose، graphicsLayer متاح للتحويلات (scale، rotationX، translationX وغيرها)، ولكن للتحويلات المعقدة لـ Bitmap، تُستخدم ماتريكس في كود drawWithContent أو drawBehind.

الملخص

  • ماتريكس — فئة أندرويد للتحويلات الأفينية والمنظورية بمصفوفة 3×3
  • أربعة أنواع أساسية: translate، scale، rotate، skew
  • عمليات pre/post تتحكم في ترتيب التطبيق: pre — قبل التحويلات الحالية، post — بعد التحويلات الحالية
  • setPolyToPoly — دالة فريدة لحساب تحويل المنظور من 4 أزواج نقاط
  • تُطبق ماتريكس على Canvas عبر concat، وعلى Bitmap عبر createBitmap مع ماتريكس، وعلى النقاط عبر mapPoints
  • invert يحسب التحويل العكسي، ويعيد false للمصفوفات الشاذة
  • isAffine وisIdentity تساعدان في تصنيف حالة المصفوفة للتحسين

سنقوم بتطوير تطبيق جوال جاهز

تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.

مناقشة المشروع

اقرأ أيضًا