الرسم على كائنات اللوحات

يُعد هذا الدرس التطبيقي جزءًا من الدورة التدريبية المتقدّمة لنظام التشغيل Android في لغة Kotlin. ستحصل على أقصى استفادة من هذه الدورة التدريبية إذا كنت تعمل من خلال الدروس التطبيقية حول الترميز بالتسلسل، ولكن هذا ليس إلزاميًا. يتم إدراج جميع الدروس التطبيقية حول ترميز الدورات التدريبية في الصفحة المقصودة لبرنامج Android المتقدّم في لغة ترميز Kotlin.

مقدمة

في نظام التشغيل Android، تتوفر لديك عدة أساليب لتطبيق الرسومات المتحركة الثنائية الأبعاد والصور المتحركة في طرق العرض.

بالإضافة إلى استخدام قابلة للرسم، يمكنك إنشاء رسومات ثنائية الأبعاد باستخدام طرق الرسم في صف Canvas. Canvas هو سطح رسم ثنائي الأبعاد يوفّر طرقًا للرسم. وتكون هذه الطريقة مفيدة عندما يحتاج تطبيقك إلى إعادة رسم نفسه بانتظام، لأن ما يراه المستخدم يتغيّر مع مرور الوقت. في هذا الدرس التطبيقي حول الترميز، ستتعرّف على كيفية إنشاء لوحة رسم ورسمها على View.

تشمل أنواع العمليات التي يمكنك إجراؤها على لوحة الرسم ما يلي:

  • املأ اللوحة بأكملها باللون.
  • ارسم الأشكال، مثل المستطيلات والأقواس والمسارات على النحو المحدّد في عنصر Paint. يحتوي العنصر Paint على معلومات عن النمط واللون حول كيفية رسم الأشكال الهندسية (مثل الخط والمستطيل والبيضاوي والمسارات)، أو على سبيل المثال نمط الخط.
  • تطبيق التحويلات، مثل الترجمة أو القياس أو التحويلات المخصصة.
  • المقطع، أي تطبيق شكل أو مسار على اللوحة لتحديد أجزائها المرئية.

تصوّر Android للرسم (مبسّط للغاية)

الرسم في Android أو أي نظام حديث آخر، هو عملية معقدة تشتمل على طبقات من التجريدات والتحسينات على الأجهزة. تشكّل آلية Android موضوعًا رائعًا للكتّاب الذي يُكتَب الكثير من التفاصيل، وتتجاوز تفاصيل هذا الدرس التطبيقي هذا الدرس التطبيقي حول الترميز.

في سياق هذا الدرس التطبيقي، وتطبيقه الذي يرسم على لوحة للعرض في وضع ملء الشاشة، يمكنك التفكير في ذلك بالطريقة التالية.

  1. تحتاج إلى طريقة عرض لعرض ما ترسمه. قد تكون هذه إحدى طرق العرض التي يوفّرها نظام Android. أو في هذا الدرس التطبيقي حول الترميز، تُنشئ ملفًا شخصيًا مخصّصًا يُعد عرض المحتوى لتطبيقك (MyCanvasView).
  2. وكما هو الحال في جميع طرق العرض، تأتي اللوحة الخاصة (canvas).
  3. للحصول على الطريقة الأساسية للرسم على لوحة طريقة عرض، يمكنك إلغاء طريقة onDraw() والرسم على لوحة الرسم.
  4. عند إنشاء رسم، عليك تخزين ما رسمته سابقًا في ذاكرة التخزين المؤقت. هناك عدة طرق لتخزين البيانات مؤقتًا، طريقة واحدة في الصورة المصغّرة (extraBitmap)، هي حفظ سجلّ للبيانات التي رسمتها كإحداثيات وتعليمات.
  5. للرسم على صورة نقطية في ذاكرة التخزين المؤقت (extraBitmap) باستخدام واجهة برمجة تطبيقات رسم اللوحة، عليك إنشاء لوحة للتخزين المؤقت (extraCanvas) لاستخدامها في الصورة النقطية.
  6. بعد ذلك، ترسم في لوحة التخزين المؤقت (extraCanvas)، التي تسحب من الصورة المصغّرة للتخزين المؤقت (extraBitmap).
  7. لعرض كل العناصر المرسومة على الشاشة، يمكنك توجيه لوحة العرض (canvas) لرسم الصورة المطبوعة مؤقتًا (extraBitmap).

ما يجب معرفته

  • كيفية إنشاء تطبيق باستخدام نشاط وتنسيق أساسي وتشغيله باستخدام "استوديو Android".
  • كيفية ربط معالجات الأحداث بالمشاهدات.
  • كيفية إنشاء ملف شخصي مخصّص.

ما ستتعرَّف عليه

  • طريقة إنشاء Canvas والرسم عليها استجابةً للمس المستخدم.

الإجراءات التي ستنفذّها

  • يمكنك إنشاء تطبيق يرسم الخطوط على الشاشة استجابةً للمستخدم الذي يلمس الشاشة.
  • يمكنك تسجيل أحداث الحركة، وارسم خطوطًا على لوحة يتم عرضها بملء الشاشة المخصص على الشاشة.

يستخدم تطبيق MiniPaint عرضًا مخصصًا لعرض خط استجابة للمسات المستخدم، كما هو موضح في لقطة الشاشة أدناه.

الخطوة الأولى: إنشاء مشروع MiniPaint

  1. أنشئ مشروع Kotlin جديدًا باسم MiniPaint يستخدم نموذج Empty Activity.
  2. افتح الملف app/res/values/colors.xml وأضِف اللونين التاليين.
<color name="colorBackground">#FFFF5500</color>
<color name="colorPaint">#FFFFEB3B</color>
  1. فتح styles.xml
  2. في النمط الرئيسي AppTheme، يتم استبدال DarkActionBar بـ NoActionBar. يؤدي ذلك إلى إزالة شريط الإجراءات، حتى تتمكن من الرسم بملء الشاشة.
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">

الخطوة الثانية: إنشاء الصف MyCanvasView

في هذه الخطوة، يمكنك إنشاء عرض مخصّص، MyCanvasView، للرسم.

  1. في الحزمة app/java/com.example.android.minipaint، أنشِئ ملفًا/صفًا جديدًا بلغة Kotlin باسم MyCanvasView.
  2. جعل الفئة MyCanvasView تمديد View واجتياز context: Context. قبول عمليات الاستيراد المقترحة
import android.content.Context
import android.view.View

class MyCanvasView(context: Context) : View(context) {
}

الخطوة الثالثة. ضبط MyCanvasView كعرض المحتوى

لعرض ما سيتم رسمه في MyCanvasView، يجب إعداده كطريقة عرض المحتوى لـ MainActivity.

  1. افتح strings.xml وحدِّد سلسلة لاستخدامها في وصف محتوى الملف الشخصي.
<string name="canvasContentDescription">Mini Paint is a simple line drawing app.
   Drag your fingers to draw. Rotate the phone to clear.</string>
  1. فتح MainActivity.kt
  2. في onCreate()، احذف setContentView(R.layout.activity_main).
  3. أنشِئ مثيل MyCanvasView.
val myCanvasView = MyCanvasView(this)
  1. أسفل ذلك، اطلب ملء الشاشة لتنسيق myCanvasView. ويمكنك إجراء ذلك من خلال ضبط علامة SYSTEM_UI_FLAG_FULLSCREEN على myCanvasView. وبهذه الطريقة، تملأ طريقة العرض بالكامل الشاشة بالكامل.
myCanvasView.systemUiVisibility = SYSTEM_UI_FLAG_FULLSCREEN
  1. أضِف وصفًا للمحتوى.
myCanvasView.contentDescription = getString(R.string.canvasContentDescription)
  1. أسفل المحتوى، اضبط عرض المحتوى على myCanvasView.
setContentView(myCanvasView)
  1. شغِّل تطبيقك. ستظهر لك شاشة بيضاء تمامًا، لأن لوحة الرسم لا بحجمها ولم ترسم أي شيء بعد.

الخطوة الأولى: تجاوز onSizeChanged()

يستدعي نظام Android طريقة onSizeChanged() كلما تغيّر حجم الملف الشخصي. ونظرًا لأنّ العرض يبدأ بدون حجم، يتم أيضًا استدعاء طريقة onSizeChanged() في الملف الشخصي بعد إعداد النشاط لأول مرة وتضخيمه. وبالتالي، فإن طريقة onSizeChanged() هذه هي المكان المثالي لإنشاء لوحة العرض وإعدادها.

  1. في MyCanvasView، حدّد متغيّرات على لوحة الرسم البياني وصورة مصغّرة على مستوى الصف. الْاتِّصَالْ بِـ extraCanvas وِextraBitmap. هذه صورة نقطية لك ولوحة للتخزين المؤقت الذي تم رسمه من قبل.
private lateinit var extraCanvas: Canvas
private lateinit var extraBitmap: Bitmap
  1. حدِّد متغيّرًا على مستوى الفئة backgroundColor للون خلفية اللوحة، واضبطه على colorBackground التي حدّدتها سابقًا.
private val backgroundColor = ResourcesCompat.getColor(resources, R.color.colorBackground, null)
  1. في MyCanvasView، ألغِ طريقة onSizeChanged(). يستدعي نظام Android أبعاد طريقة العرض هذه باستخدام أبعاد الشاشة التي تم تغييرها، أي بعرض وارتفاع جديدين (للتغيير إلى) والعرض والارتفاع القديمين (للتغيير من).
override fun onSizeChanged(width: Int, height: Int, oldWidth: Int, oldHeight: Int) {
   super.onSizeChanged(width, height, oldWidth, oldHeight)
}
  1. داخل onSizeChanged()، يمكنك إنشاء مثيل Bitmap باستخدام العرض والارتفاع الجديديْن، وهما حجم الشاشة، وتعيينه لـ extraBitmap. الوسيطة الثالثة هي ضبط لون صورة نقطية. تخزّن ARGB_8888 كل لون بـ 4 بايت، ويوصى بذلك.
extraBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
  1. أنشِئ مثيل Canvas من extraBitmap وخصِّصه إلى extraCanvas.
 extraCanvas = Canvas(extraBitmap)
  1. حدِّد لون الخلفية الذي تريد ملء extraCanvas فيه.
extraCanvas.drawColor(backgroundColor)
  1. بالنظر إلى onSizeChanged()، يتم إنشاء صورة مصغّرة ولوحات جديدة في كل مرة يتم فيها تنفيذ الدالة. يجب الحصول على صورة نقطية جديدة، لأنّ الحجم قد تغيّر. ومع ذلك، يُعد هذا تسرُّبًا للذاكرة، ما يؤدي إلى ترك الصور المصغرة القديمة في مكان قريب. ولحلّ هذه المشكلة، يُرجى إعادة تدوير extraBitmap قبل إنشاء الرمز التالي من خلال إضافة هذا الرمز بعد المكالمة مباشرةً إلى super.
if (::extraBitmap.isInitialized) extraBitmap.recycle()

الخطوة الثانية: تجاوز onDraw()

يتم إجراء جميع أعمال الرسم باللغة MyCanvasView في onDraw().

للبدء، اعرض اللوحة، واملأ الشاشة بلون الخلفية الذي عيّنته في onSizeChanged().

  1. يمكنك إلغاء onDraw() وارسم محتوى extraBitmap المخزن مؤقتًا على اللوحة المرتبطة بالملف الشخصي. تتوفر طريقة drawBitmap() Canvas بعدة إصدارات. في هذا الرمز، أنت تقدّم الصورة النقطية والإحداثيّين"س"و"ص" (بالبكسل) في أعلى يمين الشاشة، وnull للرمز Paint، وستضبط ذلك لاحقًا.
override fun onDraw(canvas: Canvas) {
   super.onDraw(canvas)
canvas.drawBitmap(extraBitmap, 0f, 0f, null)
}


لاحظ أن اللوحة التي تم تمريرها إلى onDraw() واستخدمها النظام لعرض الصورة الرمزية مختلفة عن تلك التي أنشأتها في الطريقة onSizeChanged() واستخدمتها للرسم على الصورة الرمزية.

  1. شغِّل تطبيقك. من المفترض أن تظهر الشاشة بأكملها ممتلئة بلون الخلفية المحدد.

للرسم، تحتاج إلى عنصر Paint يحدد كيفية تصميم العناصر عند الرسم، وPath الذي يحدد ما يتم رسمه.

الخطوة الأولى: إعداد كائن عرض محتوى الصفحة

  1. في MyCanvasView.kt، على مستوى الملف العلوي، حدِّد ثابت عرض الخط.
private const val STROKE_WIDTH = 12f // has to be float
  1. على مستوى الفئة MyCanvasView، حدِّد متغيّر drawColor للاحتفاظ باللون للرسم باستخدامه، وإعداده باستخدام مورد colorPaint الذي حدّدته سابقًا.
private val drawColor = ResourcesCompat.getColor(resources, R.color.colorPaint, null)
  1. على مستوى الفئة أدناه، أضِف المتغيّر paint لكائن Paint واضبطه على النحو التالي.
// Set up the paint with which to draw.
private val paint = Paint().apply {
   color = drawColor
   // Smooths out edges of what is drawn without affecting shape.
   isAntiAlias = true
   // Dithering affects how colors with higher-precision than the device are down-sampled.
   isDither = true
   style = Paint.Style.STROKE // default: FILL
   strokeJoin = Paint.Join.ROUND // default: MITER
   strokeCap = Paint.Cap.ROUND // default: BUTT
   strokeWidth = STROKE_WIDTH // default: Hairline-width (really thin)
}
  • color من paint هو drawColor الذي حددته سابقًا.
  • يحدّد isAntiAlias ما إذا كان سيتم تطبيق تنعيم الحواف. يؤدي ضبط السياسة isAntiAlias على true إلى تسوية حواف العناصر المرسومة بدون التأثير في الشكل.
  • يؤثر isDither، عندما true، في كيفية خفض دقة الألوان مع دقة أعلى من الجهاز. على سبيل المثال، يكون التخفيف هو الطريقة الأكثر شيوعًا لخفض نطاق ألوان الصور إلى 256 لونًا (أو أقل).
  • style يحدّد نوع الرسم الذي يجب تنفيذه بالضربة، وهو سطر. تحدِّد Paint.Style ما إذا كان العنصر الرئيسي المرسوم ممتلئًا أو مشطوبًا أو كلاهما (باللون نفسه). وتكون القيمة التلقائية هي ملء العنصر الذي يتم تطبيق الرسم عليه. (&"ملء&;;الألوان الداخلية للشكل, بينما يتبع الإ&جراء&نقشية&على لوحة الرسم الخاصة به.)
  • يحدّد strokeJoin من Paint.Join كيفية انضمام الخطوط والشرائح المنحنية إلى مسار يتوسطه خط. الإعداد التلقائي هو MITER.
  • تضبط strokeCap شكل نهاية السطر لتكون حدًا أقصى. ويحدِّد Paint.Cap كيفية بداية الخطوط والمسارات المرسومة ونهايتها. الإعداد التلقائي هو BUTT.
  • يحدد strokeWidth عرض السكة الحديدية بوحدات البكسل. الإعداد التلقائي هو عرض خط الشعر، الذي يكون رقيقًا حقًا، لذا تم ضبطه على ثابت STROKE_WIDTH الذي حدّدته سابقًا.

الخطوة الثانية: إعداد كائن المسار

Path هو مسار ما يرسمه المستخدم.

  1. في MyCanvasView، أضِف المتغيّر path واضبطه باستخدام كائن Path لتخزين المسار المرسوم عند متابعة لمس المستخدم للشاشة. استيراد android.graphics.Path Path.
private var path = Path()

الخطوة الأولى: الاستجابة للحركة على الشاشة

يتم استدعاء الطريقة onTouchEvent() في الملف الشخصي كلما لمس المستخدم الشاشة.

  1. في MyCanvasView، يمكنك إلغاء الطريقة onTouchEvent() لتخزين إحداثيات x وy بين ذاكرة التخزين المؤقت التي تم تمريرها في event مؤقتًا. بعد ذلك، يمكنك استخدام تعبير when للتعامل مع أحداث الحركة التي تؤدي إلى اللمس على الشاشة وتحريك الشاشة وتحرير اللمس على الشاشة. هذه هي الأحداث التي تهمّك لرسم خط على الشاشة. بالنسبة إلى كل نوع من أحداث الحدث، يمكنك استدعاء طريقة دفع، كما هو موضح في الرمز أدناه. يُرجى الاطِّلاع على مستندات صف MotionEvent للحصول على قائمة كاملة بأحداث اللمس.
override fun onTouchEvent(event: MotionEvent): Boolean {
   motionTouchEventX = event.x
   motionTouchEventY = event.y

   when (event.action) {
       MotionEvent.ACTION_DOWN -> touchStart()
       MotionEvent.ACTION_MOVE -> touchMove()
       MotionEvent.ACTION_UP -> touchUp()
   }
   return true
}
  1. على مستوى الفئة، أضِف المتغيرَين motionTouchEventX وmotionTouchEventY غير المُتَبعَين للتخزين المؤقت لإحداثيّي x وy لحدث اللمس الحالي (إحداثيات MotionEvent). ابدأ الإعداد في 0f.
private var motionTouchEventX = 0f
private var motionTouchEventY = 0f
  1. إنشاء رموز بديلة للدوال الثلاث touchStart() وtouchMove() وtouchUp().
private fun touchStart() {}

private fun touchMove() {}

private fun touchUp() {}
  1. من المفترض أن يتم إنشاء الرمز وتشغيله، ولكن لن ترى أي شيء مختلف عن الخلفية الملونة حتى الآن.

الخطوة الثانية: تنفيذ touchStart()

يتم استدعاء هذه الطريقة عندما يلمس المستخدم الشاشة لأول مرة.

  1. على مستوى الفئة، أضِف متغيّرات لتخزين أحدث قيم x وy. بعد توقف المستخدم عن الحركة ورفع اللمس، تكون هذه هي نقطة بداية المسار التالي (الجزء التالي من السطر الذي سيتم رسمه).
private var currentX = 0f
private var currentY = 0f
  1. نفِّذ طريقة touchStart() على النحو التالي. يمكنك إعادة ضبط path، والانتقال إلى إحداثيات x-y لحدث اللمس (motionTouchEventX وmotionTouchEventY)، وتخصيص currentX وcurrentY لهذه القيمة.
private fun touchStart() {
   path.reset()
   path.moveTo(motionTouchEventX, motionTouchEventY)
   currentX = motionTouchEventX
   currentY = motionTouchEventY
}

الخطوة الثالثة. تنفيذ touchTouch()

  1. على مستوى الصف، أضِف المتغيّر touchTolerance واضبطه على ViewConfiguration.get(context).scaledTouchSlop.
private val touchTolerance = ViewConfiguration.get(context).scaledTouchSlop

باستخدام أحد المسارات، لا يلزم رسم كل وحدة بكسل وطلب كل مرة تحديث شاشة. بدلاً من ذلك، يمكنك (وسيتم) دمج مسار بين النقاط لتحقيق أداء أفضل بكثير.

  • إذا لم يتحرك الإصبع إلا، فلن تكون هناك حاجة للرسم.
  • إذا تم تحريك الإصبع على مسافة أقل من touchTolerance، لا ترسم.
  • تعرض scaledTouchSlop المسافة بالبكسل التي يمكن أن تلمسها اللمس قبل أن يعتقد النظام أن المستخدم ينتقل.
  1. عرّف الطريقة touchMove(). احسب المسافة التي تم قطعها (dx، dy)، وأنشئ منحنى بين النقطتين وتخزينه في path، وعدِّل سجلّي currentX وcurrentY الجاريين، وارسم path. ويمكنك بعد ذلك الاتصال بالرقم invalidate() لفرض إعادة رسم الشاشة باستخدام السمة path المُعدَّلة.
private fun touchMove() {
   val dx = Math.abs(motionTouchEventX - currentX)
   val dy = Math.abs(motionTouchEventY - currentY)
   if (dx >= touchTolerance || dy >= touchTolerance) {
       // QuadTo() adds a quadratic bezier from the last point,
       // approaching control point (x1,y1), and ending at (x2,y2).
       path.quadTo(currentX, currentY, (motionTouchEventX + currentX) / 2, (motionTouchEventY + currentY) / 2)
       currentX = motionTouchEventX
       currentY = motionTouchEventY
       // Draw the path in the extra bitmap to cache it.
       extraCanvas.drawPath(path, paint)
   }
   invalidate()
}

هذه الطريقة بمزيد من التفصيل:

  1. حساب المسافة التي تم نقلها (dx, dy).
  2. وإذا كانت الحركة أبعد من أن تلمس اللمس، أضف شريحة إلى المسار.
  3. اضبط نقطة البداية الخاصة بالشريحة التالية على نقطة نهاية هذه الشريحة.
  4. باستخدام quadTo() بدلاً من lineTo()، أنشئ خطًا مرسومًا بسلاسة بدون زوايا. راجِع منحنيات بيزير.
  5. يمكنك استدعاء تطبيق invalidate() لإجراء (الاتصال بـ onDraw() في النهاية) وإعادة رسم العرض.

الخطوة 4: تنفيذ touchUp()

عندما يرفع المستخدم اللمس، لا يلزم سوى إعادة ضبط المسار حتى لا يتم رسمه مرة أخرى. لم يتم رسم أي عنصر، لذلك لا حاجة إلى إلغاء الصلاحية.

  1. نفِّذ الطريقة touchUp().
private fun touchUp() {
   // Reset the path so it doesn't get drawn again.
   path.reset()
}
  1. شغِّل الرمز واستخدِم إصبعك للرسم على الشاشة. لاحظ أنه في حال تدوير الجهاز، سيتم محو الشاشة لأنه لم يتم حفظ حالة الرسم. في هذا التطبيق النموذجي، تم تصميم ذلك لمنح المستخدم طريقة بسيطة لمحو الشاشة.

الخطوة 5: رسم إطار حول المخطط

أثناء رسم المستخدم على الشاشة، ينشئ تطبيقك المسار ويحفظه في صورة نقطية extraBitmap. تعرض طريقة onDraw() الصورة الرمزية الإضافية في لوحة العرض. يمكنك تنفيذ المزيد من الرسومات في onDraw(). على سبيل المثال، يمكنك رسم أشكال بعد رسم صورة نقطية.

في هذه الخطوة، ترسِم إطارًا حول حافة الصورة.

  1. في MyCanvasView، أضِف متغيّرًا باسم frame يحتوي على كائن Rect.
private lateinit var frame: Rect
  1. في نهاية onSizeChanged()، يتم تحديد قيمة داخلية، وإضافة رمز لإنشاء Rect الذي سيتم استخدامه للإطار، وذلك باستخدام الأبعاد الجديدة والأبعاد الداخلية.
// Calculate a rectangular frame around the picture.
val inset = 40
frame = Rect(inset, inset, width - inset, height - inset)
  1. في onDraw()، بعد رسم صورة نقطية، ارسم مستطيلًا.
// Draw a frame around the canvas.
canvas.drawRect(frame, paint)
  1. شغِّل تطبيقك ولاحظ الإطار.

المهمة (اختياري): تخزين البيانات في مسار

في التطبيق الحالي، يتم تخزين معلومات الرسم في صورة نقطية. على الرغم من أن هذا الحل جيد، فهو هو الطريقة الوحيدة الممكنة لتخزين معلومات الرسم. وتعتمد كيفية تخزين سجلّ الرسم على التطبيق والمتطلبات المختلفة. على سبيل المثال، إذا كنت ترسم أشكالاً، يمكنك حفظ قائمة الأشكال مع موقعها وأبعادها. بالنسبة إلى تطبيق MiniPaint، يمكنك حفظ المسار باعتباره Path. في ما يلي المخطط العام عن كيفية إجراء ذلك إذا كنت ترغب في تجربته.

  1. في MyCanvasView، أزِل كل الرموز للرمز extraCanvas وextraBitmap.
  2. إضافة متغيرات للمسار حتى الآن والمسار المرسوم حاليًا.
// Path representing the drawing so far
private val drawing = Path()

// Path representing what's currently being drawn
private val curPath = Path()
  1. في onDraw()، بدلاً من رسم صورة نقطية، ارسم المسارات المُخزَّنة والحالية.
// Draw the drawing so far
canvas.drawPath(drawing, paint)
// Draw any current squiggle
canvas.drawPath(curPath, paint)
// Draw a frame around the canvas
canvas.drawRect(frame, paint)
  1. في touchUp()، أضِف المسار الحالي إلى المسار السابق وأعِد ضبط المسار الحالي.
// Add the current path to the drawing so far
drawing.addPath(curPath)
// Rewind the current path for the next touch
curPath.reset()
  1. شغِّل تطبيقك، ولا يجب أن يكون هناك أي فرق على الإطلاق.

نزِّل الرمز للدرس التطبيقي النهائي للترميز.

$  git clone https://github.com/googlecodelabs/android-kotlin-drawing-canvas


بدلاً من ذلك، يمكنك تنزيل المستودع كملف Zip وفك ضغطه وفتحه في "استوديو Android".

تنزيل ملف Zip

  • واجهة Canvas هي مساحة رسم ثنائية الأبعاد تقدّم طرقًا للرسم.
  • يمكن ربط Canvas بمثيل View يعرضه.
  • يحتوي كائن Paint على معلومات النمط واللون حول كيفية رسم الأشكال الهندسية (مثل الخط والمستطيل والبيضاوي والمسارات) والنص.
  • يتمثل أحد الأنماط الشائعة للعمل مع لوحة الرسم في إنشاء طريقة عرض مخصصة وتجاوز طريقتي onDraw() وonSizeChanged().
  • يمكنك إلغاء الطريقة onTouchEvent() لالتقاط لمسات المستخدم والرد عليها من خلال رسم العناصر.
  • يمكنك استخدام صورة نقطية إضافية لتخزين المعلومات مؤقتًا عن الرسومات التي تتغير بمرور الوقت. ويمكنك بدلاً من ذلك تخزين الأشكال أو مسار.

دورة Udacity:

مستندات مطوّر برامج Android:

يسرد هذا القسم المهام الدراسية المحتملة للطلاب الذين يعملون من خلال هذا الدرس التطبيقي حول الترميز في إطار دورة تدريبية يُديرها معلِّم. يجب أن ينفِّذ المعلّم ما يلي:

  • يمكنك تخصيص واجب منزلي إذا لزم الأمر.
  • التواصل مع الطلاب بشأن كيفية إرسال الواجبات المنزلية
  • وضع درجات للواجبات المنزلية.

ويمكن للمعلّمين استخدام هذه الاقتراحات بقدر ما يريدون أو بقدر ما يريدون، ويجب عدم التردد في تخصيص أي واجبات منزلية أخرى مناسبة.

إذا كنت تستخدم هذا الدرس التطبيقي بنفسك، يمكنك استخدام هذه الواجبات المنزلية لاختبار معلوماتك.

الإجابة عن هذه الأسئلة

السؤال 1

أي من المكوّنات التالية مطلوبة للعمل مع Canvas؟ يُرجى اختيار كل الإجابات المناسبة.

Bitmap

Paint

Path

View

السؤال 2

ما المقصود بمكالمة invalidate() إلى (العبارات العامة)؟

▢ يعمل على إلغاء صلاحية تطبيقك وإعادة تشغيله.

▢ لمحو الرسم من الصورة الرمزية.

▢ يشير إلى ضرورة عدم تشغيل الرمز السابق.

▢ لإخبار النظام بأنّ عليه إعادة رسم الشاشة.

السؤال 3

ما هي وظيفة العناصر Canvas وBitmap وPaint؟

▢ سطح رسم ثنائي الأبعاد، صورة نقطية معروضة على الشاشة، ومعلومات أنماط للرسم.

▢ سطح رسم ثلاثي الأبعاد، صورة نقطية للتخزين المؤقت على المسار، ومعلومات تصميم للرسم.

▢ سطح رسم ثنائي الأبعاد، يتم عرض صورة نقطية على الشاشة، ونمطها في العرض.

▢ذاكرة التخزين المؤقت للحصول على معلومات الرسم والصور النقطية للرسم عليها وتصميم الأنماط للرسم

للحصول على روابط إلى دروس تطبيقية أخرى حول الترميز في هذه الدورة التدريبية، اطّلِع على الصفحة المقصودة للإصدارات المتقدّمة من Android في لغة ترميز Kotlin.