يحتاج العديد من التطبيقات إلى أن تكون قادرًا على التحكم بدقة في ما يتم رسمه على الشاشة. قد يكون هذا صغيرًا مثل وضع مربع أو دائرة على الشاشة في المكان المناسب فقط، أو قد يكون ترتيبًا متقنًا من العناصر الرسومية في العديد من الأنماط المختلفة.
رسم أساسي مع مفاتيح التعديل وDrawScope
إنّ الطريقة الأساسية لرسم عنصر مخصّص في Compose هي باستخدام مفاتيح التعديل، مثل
Modifier.drawWithContent
وModifier.drawBehind
وModifier.drawWithCache
.
على سبيل المثال، لرسم عنصر خلف العنصر القابل للإنشاء، يمكنك استخدام
أداة التعديل drawBehind
لبدء تنفيذ أوامر الرسم:
Spacer( modifier = Modifier .fillMaxSize() .drawBehind { // this = DrawScope } )
إذا كان كل ما تحتاجه هو عنصر قابل للإنشاء وجذاب، يمكنك استخدام Canvas
القابل للإنشاء. عنصر Canvas
القابل للإنشاء هو برنامج ربط مريح حول Modifier.drawBehind
. يمكنك وضع Canvas
في التنسيق بالطريقة نفسها
التي تضعها مع أي عنصر آخر في واجهة Compose. وضمن
Canvas
، يمكنك رسم عناصر مع إمكانية التحكّم الدقيق في نمطها وموقعها.
تعرض جميع معدِّلات الرسم DrawScope
، وهي بيئة رسم مُفصَّل تحافظ على حالتها الخاصة. يتيح لك هذا تعيين المعاملات لمجموعة من
العناصر الرسومية. توفّر DrawScope
عدة حقول مفيدة، مثل size
، وهي عنصر Size
يحدّد الأبعاد الحالية للسمة DrawScope
.
لرسم شيء، يمكنك استخدام إحدى دوال الرسم العديدة في DrawScope
. على سبيل المثال، ترسم التعليمة البرمجية التالية مستطيلاً في الزاوية العلوية اليسرى من الشاشة:
Canvas(modifier = Modifier.fillMaxSize()) { val canvasQuadrantSize = size / 2F drawRect( color = Color.Magenta, size = canvasQuadrantSize ) }
![مستطيل وردي مرسوم على خلفية بيضاء يشغل ربع الشاشة](https://developer.android.google.cn/static/develop/ui/compose/images/graphics/introduction/compose_graphics_draw_rect.png?authuser=1&hl=ar)
لمعرفة المزيد من المعلومات حول معدِّلات الرسم المختلفة، يمكنك الاطّلاع على مستندات معدِّلات الرسومات.
نظام الإحداثيات
لرسم عنصر على الشاشة، عليك معرفة الإزاحة (x
وy
) وحجم العنصر. في العديد من طرق الرسم على DrawScope
، يتم توفير الموضع والحجم من خلال قيم المعلَمات التلقائية. تضع المعلمات التلقائية بشكل عام
العنصر عند النقطة [0, 0]
على لوحة الرسم وتوفر علامة
size
تلقائية تملأ مساحة الرسم بأكملها، كما في المثال أعلاه. يظهر
المستطيل في أعلى يسار الصفحة. لضبط حجم العنصر وموضعه،
تحتاج إلى فهم نظام الإحداثيات في Compose.
يقع أصل نظام الإحداثيات ([0,0]
) في أعلى وحدات البكسل في أقصى اليسار في منطقة الرسم. تزيد قيمة x
كلما تحركت إلى اليمين وتزداد قيمة y
كلما تحركت
لأسفل.
![شبكة تعرض نظام الإحداثيات ويظهر أعلى اليسار [0، 0] وأسفل اليمين [العرض، الارتفاع]](https://developer.android.google.cn/static/develop/ui/compose/images/graphics/introduction/compose_coordinate_system_drawing.png?authuser=1&hl=ar)
على سبيل المثال، إذا أردت رسم خط قُطري من أعلى يسار مساحة لوحة الرسم إلى أسفل يسار الشاشة، يمكنك استخدام الدالة DrawScope.drawLine()
وتحديد إزاحة البداية والنهاية باستخدام موضعَي x وy المقابلتَين:
Canvas(modifier = Modifier.fillMaxSize()) { val canvasWidth = size.width val canvasHeight = size.height drawLine( start = Offset(x = canvasWidth, y = 0f), end = Offset(x = 0f, y = canvasHeight), color = Color.Blue ) }
التحويلات الأساسية
تقدّم DrawScope
عمليات تحويل لتغيير مكان أو كيفية تنفيذ أوامر الرسم.
المقياس
استخدِم
DrawScope.scale()
لزيادة حجم عمليات الرسم بمقدار عامل. تنطبق عمليات مثل scale()
على جميع عمليات الرسم داخل دالة lambda المقابلة. على سبيل المثال، يزيد الرمز التالي من scaleX
10 مرات وscaleY
15 مرة:
Canvas(modifier = Modifier.fillMaxSize()) { scale(scaleX = 10f, scaleY = 15f) { drawCircle(Color.Blue, radius = 20.dp.toPx()) } }
![دائرة تم قياسها بشكل غير منتظم](https://developer.android.google.cn/static/develop/ui/compose/images/graphics/introduction/compose_graphics_canvas_scale.png?authuser=1&hl=ar)
ترجمة
استخدِم رمز
DrawScope.translate()
لتحريك عمليات الرسم للأعلى أو للأسفل أو لليسار أو لليمين. على سبيل المثال، ينقل الرمز التالي الرسم 100 بكسل إلى اليمين و300 بكسل لأعلى:
Canvas(modifier = Modifier.fillMaxSize()) { translate(left = 100f, top = -300f) { drawCircle(Color.Blue, radius = 200.dp.toPx()) } }
![تم نقل دائرة خارج المركز](https://developer.android.google.cn/static/develop/ui/compose/images/graphics/introduction/compose_graphics_canvas_translate.png?authuser=1&hl=ar)
تدوير
استخدِم DrawScope.rotate()
لتدوير عمليات الرسم حول نقطة محورية. على سبيل المثال، تقوم التعليمة البرمجية التالية
بتدوير مستطيل 45 درجة:
Canvas(modifier = Modifier.fillMaxSize()) { rotate(degrees = 45F) { drawRect( color = Color.Gray, topLeft = Offset(x = size.width / 3F, y = size.height / 3F), size = size / 3F ) } }
![هاتف على شكل مستطيل تم تدويره بزاوية 45 درجة في وسط الشاشة](https://developer.android.google.cn/static/develop/ui/compose/images/graphics/introduction/compose_graphics_canvas_rotate.png?authuser=1&hl=ar)
rotate()
لتطبيق التدوير على نطاق الرسم الحالي، الذي يعمل على تدوير المستطيل بمقدار 45 درجة.
مساحة داخلية
يمكنك استخدام DrawScope.inset()
لضبط المعلَمات التلقائية للمعلَمات الحالية DrawScope
وتغيير حدود الرسم وترجمة الرسومات وفقًا لذلك:
Canvas(modifier = Modifier.fillMaxSize()) { val canvasQuadrantSize = size / 2F inset(horizontal = 50f, vertical = 30f) { drawRect(color = Color.Green, size = canvasQuadrantSize) } }
تضيف هذه التعليمة البرمجية مساحة متروكة بشكل فعّال لأوامر الرسم:
![مستطيل مبطّن من حوله](https://developer.android.google.cn/static/develop/ui/compose/images/graphics/introduction/compose_graphics_canvas_inset.png?authuser=1&hl=ar)
عمليات تحويل متعددة
لتطبيق عمليات تحويل متعددة على رسوماتك، استخدِم الدالة
DrawScope.withTransform()
التي تنشئ
وتطبّق عملية تحويل واحدة تجمع كل التغييرات المطلوبة. يُعد استخدام
withTransform()
أكثر فعالية من إجراء استدعاءات متداخلة لتحويلات فردية،
لأنه يتم تنفيذ جميع التحويلات معًا في
عملية واحدة، بدلًا من أن تحتاج ميزة Compose إلى حساب وحفظ كل
تحويل من التحويلات المتداخلة.
على سبيل المثال، تطبق التعليمة البرمجية التالية كلاً من الترجمة والتدوير على المستطيل:
Canvas(modifier = Modifier.fillMaxSize()) { withTransform({ translate(left = size.width / 5F) rotate(degrees = 45F) }) { drawRect( color = Color.Gray, topLeft = Offset(x = size.width / 3F, y = size.height / 3F), size = size / 3F ) } }
![هاتف يحتوي على مستطيل مستدير تم نقله إلى جانب الشاشة](https://developer.android.google.cn/static/develop/ui/compose/images/graphics/introduction/compose_graphics_multiple_transforms.png?authuser=1&hl=ar)
withTransform
لتطبيق كل من التدوير والترجمة، وتدوير المستطيل وتحويله إلى اليسار.عمليات الرسم الشائعة
رسم نص
لرسم نص في Compose، يمكنك عادةً استخدام عنصر Text
القابل للإنشاء. مع ذلك، إذا كنت في DrawScope
أو تريد رسم النص يدويًا باستخدام التخصيص، يمكنك استخدام الطريقة DrawScope.drawText()
.
لرسم نص، أنشئ TextMeasurer
باستخدام rememberTextMeasurer
واطلب drawText
باستخدام أداة القياس:
val textMeasurer = rememberTextMeasurer() Canvas(modifier = Modifier.fillMaxSize()) { drawText(textMeasurer, "Hello") }
![عرض رسالة ترحيب مرسومة على لوحة رسم](https://developer.android.google.cn/static/develop/ui/compose/images/graphics/introduction/compose_graphics_draw_text.png?authuser=1&hl=ar)
قياس النص
يعمل نص الرسم بشكل مختلف قليلاً عن أوامر الرسم الأخرى. عادةً، تعطي أمر الرسم الحجم (العرض والارتفاع) لرسم الشكل/الصورة به. تتوفّر في النص بعض المعلَمات التي تتحكّم في حجم النص المعروض، مثل حجم الخط والخط والأحرف المتصلة والمسافات بين الأحرف.
من خلال ميزة Compose، يمكنك استخدام TextMeasurer
للوصول إلى حجم النص الذي تم قياسه، اعتمادًا على العوامل المذكورة أعلاه. إذا كنت ترغب في رسم خلفية
خلف النص، يمكنك استخدام المعلومات التي تم قياسها للحصول على حجم
المنطقة التي يشغلها النص:
val textMeasurer = rememberTextMeasurer() Spacer( modifier = Modifier .drawWithCache { val measuredText = textMeasurer.measure( AnnotatedString(longTextSample), constraints = Constraints.fixedWidth((size.width * 2f / 3f).toInt()), style = TextStyle(fontSize = 18.sp) ) onDrawBehind { drawRect(pinkColor, size = measuredText.size.toSize()) drawText(measuredText) } } .fillMaxSize() )
ينتج مقتطف الرمز هذا خلفية وردية على النص:
![نص متعدد الأسطر يشغل حجم 2⁄3 من المساحة الكاملة، مع مستطيل للخلفية](https://developer.android.google.cn/static/develop/ui/compose/images/graphics/introduction/compose_graphics_canvas_draw_text_measured.png?authuser=1&hl=ar)
يؤدي ضبط القيود أو حجم الخط أو أي خاصية تؤثر على الحجم الذي يتم قياسه
إلى حجم جديد يتم الإبلاغ عنه. يمكنك ضبط حجم ثابت لكلٍّ من width
وheight
، ويتّبع النص المجموعة TextOverflow
. على سبيل المثال، يعرض الرمز التالي النص 1⁄3 من الارتفاع و1⁄3 عرض المنطقة القابلة للإنشاء، ويضبط TextOverflow
على TextOverflow.Ellipsis
:
val textMeasurer = rememberTextMeasurer() Spacer( modifier = Modifier .drawWithCache { val measuredText = textMeasurer.measure( AnnotatedString(longTextSample), constraints = Constraints.fixed( width = (size.width / 3f).toInt(), height = (size.height / 3f).toInt() ), overflow = TextOverflow.Ellipsis, style = TextStyle(fontSize = 18.sp) ) onDrawBehind { drawRect(pinkColor, size = measuredText.size.toSize()) drawText(measuredText) } } .fillMaxSize() )
يتم الآن رسم النص ضمن القيود مع علامة حذف في النهاية:
![نص مرسوم على خلفية وردية، مع علامة حذف تقطع النص.](https://developer.android.google.cn/static/develop/ui/compose/images/graphics/introduction/compose_graphics_canvas_draw_text_ellipsis.png?authuser=1&hl=ar)
TextOverflow.Ellipsis
مع قيود ثابتة على قياس النص.رسم صورة
لرسم ImageBitmap
باستخدام DrawScope
، يمكنك تحميل الصورة باستخدام ImageBitmap.imageResource()
ثم الاتصال بـ drawImage
:
val dogImage = ImageBitmap.imageResource(id = R.drawable.dog) Canvas(modifier = Modifier.fillMaxSize(), onDraw = { drawImage(dogImage) })
![صورة كلب مرسوم على "لوحة الرسم"](https://developer.android.google.cn/static/develop/ui/compose/images/graphics/introduction/compose_graphics_canvas_image.png?authuser=1&hl=ar)
ImageBitmap
" على لوحة رسمرسم أشكال أساسية
هناك العديد من دوال رسم الأشكال في DrawScope
. لرسم شكل، استخدم إحدى
دوال الرسم المحددة مسبقًا، مثل drawCircle
:
val purpleColor = Color(0xFFBA68C8) Canvas( modifier = Modifier .fillMaxSize() .padding(16.dp), onDraw = { drawCircle(purpleColor) } )
واجهة برمجة التطبيقات |
ناتج |
![]() |
|
![]() |
|
![]() |
|
![]() |
|
![]() |
|
![]() |
|
![]() |
رسم مسار
المسار هو سلسلة من التعليمات الرياضية التي تؤدي إلى رسم بمجرد تنفيذه. يمكن لـ DrawScope
رسم مسار باستخدام الطريقة DrawScope.drawPath()
.
على سبيل المثال، لنفترض أنّك أردت رسم مثلث. ويمكنك إنشاء مسار بدوال مثل lineTo()
وmoveTo()
باستخدام حجم منطقة الرسم.
بعد ذلك، يمكنك طلب drawPath()
باستخدام هذا المسار الذي تم إنشاؤه حديثًا للحصول على مثلث.
Spacer( modifier = Modifier .drawWithCache { val path = Path() path.moveTo(0f, 0f) path.lineTo(size.width / 2f, size.height / 2f) path.lineTo(size.width, 0f) path.close() onDrawBehind { drawPath(path, Color.Magenta, style = Stroke(width = 10f)) } } .fillMaxSize() )
![مثلث مسار أرجواني مقلوب مرسوم في علامة التبويب Compose](https://developer.android.google.cn/static/develop/ui/compose/images/graphics/introduction/compose_graphics_canvas_draw_path.png?authuser=1&hl=ar)
Path
ورسمه في Composeجارٍ الوصول إلى عنصر واحد (Canvas
)
من خلال DrawScope
، ليس لديك إمكانية الوصول المباشر إلى عنصر Canvas
. يمكنك استخدام DrawScope.drawIntoCanvas()
للوصول إلى كائن Canvas
نفسه الذي يمكنك استدعاء الدوال عليه.
على سبيل المثال، إذا كان لديك عنصر Drawable
مخصّص تريد رسمه على اللوحة، يمكنك الوصول إلى اللوحة واستدعاء Drawable#draw()
، مع تمرير الكائن Canvas
:
val drawable = ShapeDrawable(OvalShape()) Spacer( modifier = Modifier .drawWithContent { drawIntoCanvas { canvas -> drawable.setBounds(0, 0, size.width.toInt(), size.height.toInt()) drawable.draw(canvas.nativeCanvas) } } .fillMaxSize() )
![شكل بيضاوي أسود قابل للرسم بحجم كامل](https://developer.android.google.cn/static/develop/ui/compose/images/graphics/introduction/compose_graphics_canvas_draw_into_canvas.png?authuser=1&hl=ar)
Drawable
.مزيد من المعلومات
لمزيد من المعلومات حول "الرسم في Compose"، ألق نظرة على الموارد التالية:
- معدِّلات الرسومات - يمكنك التعرّف على الأنواع المختلفة لتعديلات الرسم.
- الفرشاة - تعرَّف على طريقة تخصيص رسمة المحتوى.
- التنسيقات والرسومات المخصَّصة في Compose - Android Dev Summit لعام 2022 - تعرَّف على كيفية إنشاء واجهة مستخدم مخصَّصة في Compose باستخدام التنسيقات والرسومات.
- نموذج JetLagged - إنشاء نموذج يوضح كيفية رسم رسم بياني مخصص.
أفلام مُقترَحة لك
- ملاحظة: يظهر نص الرابط عند إيقاف JavaScript
- معدِّلات الرسومات
- الرسومات في Compose
- خطوط المحاذاة في Jetpack Compose