عندما تحتاج إلى عرض صور ثابتة في تطبيقك، يمكنك استخدام الفئة Drawable
وفئاتها الفرعية لرسم أشكال
الصور. Drawable
هو تجريد عام
شيء يمكن رسمه. وتساعد الفئات الفرعية المختلفة في الحصول على صورة محددة
ويمكنك توسيعها لتحديد الكائنات القابلة للرسم
تتصرف بطرق فريدة.
هناك طريقتان لتحديد Drawable
وإنشاء مثيل منه إلى جانب استخدام الدوال الإنشائية للفئة:
- تضخيم مورد الصور (ملف الصور النقطية) المحفوظ في مشروعك.
- تضخيم مورد XML الذي يحدد السمات القابلة للرسم
ملاحظة: قد تفضل بدلاً من ذلك استخدام متجه قابل للرسم، والذي يحدد صورة بمجموعة من النقاط والخطوط والمنحنيات، إلى جانب معلومات اللون المرتبطة بها. يسمح هذا بإتاحة رسم المتجهات ليتم قياسها لتناسب أحجام مختلفة دون فقدان الجودة. لمزيد من المعلومات، يُرجى الاطّلاع على قسم متّجه نظرة عامة على العناصر القابلة للرسم.
إنشاء عناصر قابلة للرسم من صور الموارد
يمكنك إضافة رسومات إلى تطبيقك من خلال الإشارة إلى ملف صورة من موارد المشروع. أنواع الملفات المعتمدة هي PNG (الخيار المفضّل) وJPG (مقبول) وGIF (لا يُنصح باستخدامها) رموز التطبيقات والشعارات والرسومات الأخرى، مثل الرسومات المستخدَمة في الألعاب، هي مناسبة تمامًا لهذه التقنية.
لاستخدام مورد صور، أضِف ملفك إلى res/drawable/
.
دليل مشروعك. بعد الوصول إلى مشروعك، يمكنك الرجوع إلى الصورة
من الرمز البرمجي أو تنسيق XML. وفي كلتا الحالتين، يشار إليه باستخدام
ومعرّف المورد، وهو اسم الملف بدون امتداد نوع الملف. بالنسبة
على سبيل المثال، ارجع إلى my_image.png
باسم my_image
.
ملاحظة: تتوفّر موارد الصور في
قد يتم تحسين الدليل res/drawable/
تلقائيًا باستخدام
ضغط الصور بدون فقدان البيانات باستخدام أداة aapt
أثناء عملية التصميم
الدفع. على سبيل المثال، ملف PNG باللون الحقيقي لا يتطلب أكثر من 256 لونًا
يمكن تحويلها إلى ملف PNG بحجم 8 بت مع لوحة ألوان. ينتج عن ذلك صورة
بجودة متساوية ولكن تتطلب ذاكرة أقل. نتيجةً لذلك، تصبح الصور الثنائية
الموضوعة في هذا الدليل يمكن أن تتغير في وقت الإنشاء. إذا كنت تخطط لقراءة
وتحويلها إلى صورة نقطية، فضع صورك في
res/raw/
بدلاً من ذلك، حيث لا تفعل الأداة aapt
وتعديلها.
يوضح مقتطف الرمز التالي كيفية إنشاء ImageView
يستخدم
صورة تم إنشاؤها من مورد قابل للرسم وتضيفها إلى التخطيط:
Kotlin
private lateinit var constraintLayout: ConstraintLayout override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // Instantiate an ImageView and define its properties val i = ImageView(this).apply { setImageResource(R.drawable.my_image) contentDescription = resources.getString(R.string.my_image_desc) // set the ImageView bounds to match the Drawable's dimensions adjustViewBounds = true layoutParams = ViewGroup.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT) } // Create a ConstraintLayout in which to add the ImageView constraintLayout = ConstraintLayout(this).apply { // Add the ImageView to the layout. addView(i) } // Set the layout as the content view. setContentView(constraintLayout) }
Java
ConstraintLayout constraintLayout; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Create a ConstraintLayout in which to add the ImageView constraintLayout = new ConstraintLayout(this); // Instantiate an ImageView and define its properties ImageView i = new ImageView(this); i.setImageResource(R.drawable.my_image); i.setContentDescription(getResources().getString(R.string.my_image_desc)); // set the ImageView bounds to match the Drawable's dimensions i.setAdjustViewBounds(true); i.setLayoutParams(new ViewGroup.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); // Add the ImageView to the layout and set the layout as the content view. constraintLayout.addView(i); setContentView(constraintLayout); }
في حالات أخرى، قد تحتاج إلى التعامل مع مورد الصور باعتباره كائن Drawable
، كما هو موضّح في ما يلي
مثال:
Kotlin
val myImage: Drawable = ResourcesCompat.getDrawable(context.resources, R.drawable.my_image, null)
Java
Resources res = context.getResources(); Drawable myImage = ResourcesCompat.getDrawable(res, R.drawable.my_image, null);
تحذير: يشير هذا المصطلح إلى كل مورد فريد في مشروعك.
يمكنك الاحتفاظ بحالة واحدة فقط، بغض النظر عن عدد العناصر المختلفة
لإنشاء مثيل لها. على سبيل المثال، في حال إنشاء مثيل كائنَين Drawable
من مورد الصور نفسه
تغيير خاصية (مثل ألفا) لكائن واحد، فسيؤثر ذلك أيضًا
الأخرى. عند التعامل مع مثيلات متعددة لمورد صورة، بدلاً من
من تحويل الكائن Drawable
مباشرةً، يجب تنفيذ
ما قبل سن المراهقة
صورة متحركة.
يوضّح مقتطف XML أدناه كيفية إضافة مورد قابل للرسم إلى ImageView
بتنسيق XML:
<ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/my_image" android:contentDescription="@string/my_image_desc" />
لمزيد من المعلومات حول استخدام موارد المشاريع، يُرجى الاطّلاع على الموارد ومواد العرض.
ملاحظة: عند استخدام موارد الصور كمصدر للرسومات، تأكد من أن الصور ذات الحجم المناسب لمختلف كثافات وحدات البكسل. إذا كانت الصور غير صحيحة، فسيتم تغيير حجمها للملاءمة، مما قد يؤدي إلى وجود عناصر في العناصر القابلة للرسم. لمزيد من المعلومات، يُرجى قراءة المقالة دعم مختلف بكثافة وحدات البكسل.
إنشاء عناصر للرسم من موارد XML
إذا كان هناك Drawable
الذي ترغب في إنشائه، والذي لا يعتمد في البداية على المتغيرات التي تحددها
أو تفاعل المستخدم، وبالتالي سيكون تحديد Drawable
في XML خيارًا جيدًا. بالتساوي
إذا كنت تتوقع أن تغيّر "Drawable
" خصائصه أثناء تفاعل المستخدم
مع تطبيقك، يجب أن تضع في اعتبارك تعريف الكائن في XML، حيث يمكنك تعديل الخصائص بعد ذلك
تم إنشاء مثيل للكائن.
بعد تحديد Drawable
في XML، احفظ الملف في
دليل res/drawable/
لمشروعك. يوضح المثال التالي ملف XML الذي
تحدد
TransitionDrawable
المصدر، الذي يرث من Drawable
:
<!-- res/drawable/expand_collapse.xml --> <transition xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/image_expand"/> <item android:drawable="@drawable/image_collapse"/> </transition>
ثم استرجع الكائن وأنشئ مثيلاً له عن طريق استدعاء
Resources#getDrawable()
وتمرير معرّف المورد لملف XML الخاص بك. أي تقييم
فئة فرعية واحدة (Drawable
)
التي تدعم طريقة inflate()
، ويمكن تحديدها في XML وإنشاء مثيل لها
حسب تطبيقك.
تستخدم كل فئة قابلة للرسم تتوافق مع تضخيم XML سمات XML محدّدة.
تساعد في تعريف خصائص الكائن. تنشئ التعليمة البرمجية التالية مثيلاً
TransitionDrawable
وتعيينه كمحتوى
كائن ImageView
:
Kotlin
val transition= ResourcesCompat.getDrawable( context.resources, R.drawable.expand_collapse, null ) as TransitionDrawable val image: ImageView = findViewById(R.id.toggle_image) image.setImageDrawable(transition) // Description of the initial state that the drawable represents. image.contentDescription = resources.getString(R.string.collapsed) // Then you can call the TransitionDrawable object's methods. transition.startTransition(1000) // After the transition is complete, change the image's content description // to reflect the new state.
Java
Resources res = context.getResources(); TransitionDrawable transition = (TransitionDrawable) ResourcesCompat.getDrawable(res, R.drawable.expand_collapse, null); ImageView image = (ImageView) findViewById(R.id.toggle_image); image.setImageDrawable(transition); // Description of the initial state that the drawable represents. image.setContentDescription(getResources().getString(R.string.collapsed)); // Then you can call the TransitionDrawable object's methods. transition.startTransition(1000); // After the transition is complete, change the image's content description // to reflect the new state.
لمزيد من المعلومات حول سمات XML المتوافقة، يمكنك الاطّلاع على الفئات. الواردة أعلاه.
أشكال قابلة للرسم
يمكن أن يكون العنصر ShapeDrawable
خيارًا جيدًا
عندما تريد رسم رسم ثنائي الأبعاد ديناميكيًا. يمكنك
رسم الأشكال الأساسية آليًا على عنصر ShapeDrawable
وتطبيق الأنماط التي يحتاجها تطبيقك.
ShapeDrawable
هي فئة فرعية من Drawable
. لهذا السبب، يمكنك استخدام
ShapeDrawable
حيثما كان من المتوقع وجود Drawable
. بالنسبة
على سبيل المثال، يمكنك استخدام كائن ShapeDrawable
لضبط الخلفية.
العرض من خلال تمريره إلى طريقة العرض setBackgroundDrawable()
. يمكنك أيضًا رسم الشكل الخاص بك
طريقة عرض مخصصة لك وإضافتها إلى تخطيط في تطبيقك.
بما أنّ ShapeDrawable
يستخدم طريقة draw()
الخاصة به، يمكنك إنشاء
فئة فرعية من View
ترسم السمة ShapeDrawable
كائن أثناء الحدث onDraw()
، كما هو موضح في
مثال التعليمة البرمجية التالي:
Kotlin
class CustomDrawableView(context: Context) : View(context) { private val drawable: ShapeDrawable = run { val x = 10 val y = 10 val width = 300 val height = 50 contentDescription = context.resources.getString(R.string.my_view_desc) ShapeDrawable(OvalShape()).apply { // If the color isn't set, the shape uses black as the default. paint.color = 0xff74AC23.toInt() // If the bounds aren't set, the shape can't be drawn. setBounds(x, y, x + width, y + height) } } override fun onDraw(canvas: Canvas) { drawable.draw(canvas) } }
Java
public class CustomDrawableView extends View { private ShapeDrawable drawable; public CustomDrawableView(Context context) { super(context); int x = 10; int y = 10; int width = 300; int height = 50; setContentDescription(context.getResources().getString( R.string.my_view_desc)); drawable = new ShapeDrawable(new OvalShape()); // If the color isn't set, the shape uses black as the default. drawable.getPaint().setColor(0xff74AC23); // If the bounds aren't set, the shape can't be drawn. drawable.setBounds(x, y, x + width, y + height); } protected void onDraw(Canvas canvas) { drawable.draw(canvas); } }
يمكنك استخدام الفئة CustomDrawableView
في عيّنة الرمز البرمجي.
أعلاه كما تستخدم أي طريقة عرض مخصّصة أخرى. على سبيل المثال، يمكنك
إضافتها آليًا إلى نشاط في تطبيقك، كما هو موضح في ما يلي
مثال:
Kotlin
private lateinit var customDrawableView: CustomDrawableView override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) customDrawableView = CustomDrawableView(this) setContentView(customDrawableView) }
Java
CustomDrawableView customDrawableView; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); customDrawableView = new CustomDrawableView(this); setContentView(customDrawableView); }
إذا أردت استخدام طريقة العرض المخصّصة في تنسيق XML بدلاً من ذلك،
يجب أن تلغي الفئة CustomDrawableView
الدالة الإنشائية View(Context, AttributeSet)
، والتي يتم استدعاؤها عند إدخال الفئة.
مضخمة من XML. يوضح المثال التالي كيفية الإعلان عن
CustomDrawableView
في تنسيق XML:
<com.example.shapedrawable.CustomDrawableView android:layout_width="fill_parent" android:layout_height="wrap_content" />
إنّ صف ShapeDrawable
، مثل العديد من الصفوف الأخرى
قابلة للرسم في حزمة android.graphics.drawable
، تتيح لك
تحدد الخصائص المختلفة للكائن باستخدام الطرق العامة. مثال
الخصائص التي قد ترغب في تعديلها تشمل الشفافية ألفا، وتصفية الألوان،
السرعة والتعتيم واللون.
ويمكنك أيضًا تحديد الأشكال الأولية القابلة للرسم باستخدام موارد XML. لمزيد من المعلومات، المعلومات، راجع شكل قابل للرسم في أنواع المراجع القابلة للرسم:
عناصر NinePatch القابلة للرسم
الرسم NinePatchDrawable
هو
صورة نقطية قابلة للتمديد يمكنك استخدامها كخلفية للعرض. جهاز Android
تغيير حجم الرسم تلقائيًا لاستيعاب محتويات طريقة العرض. إنّ
مثال على استخدام صورة NinePatch هو الخلفية التي يستخدمها نظام Android
الأزرار — يجب أن تمتد الأزرار لتلائم السلاسل ذات الأطوال المختلفة. حاسمة
رسم NinePatch هو صورة PNG قياسية تتضمن حدًا إضافيًا يبلغ 1 بكسل.
يجب حفظه باستخدام الإضافة 9.png
في
دليل res/drawable/
لمشروعك.
استخدم الحدود لتحديد المناطق القابلة للتمديد والثابتة من الصورة. يمكنك الإشارة إلى قسم قابل للتمديد من خلال رسم بكسل واحد (أو أكثر) بعرض واحد (أو أكثر) الخطوط السوداء في الجزء الأيسر والعلوي من الحد (وحدات بكسل الحد الأخرى) شفافة تمامًا أو بيضاء). يمكنك إنشاء العديد من الأقسام القابلة للتمدّد كما تريد. ويظل الحجم النسبي للأقسام القابلة للتمديد كما هو، وبالتالي يظل القسم الأكبر هو الأكبر دائمًا.
ويمكنك أيضًا تحديد قسم اختياري قابل للرسم من الصورة (بشكل فعال،
خطوط المساحة المتروكة) عن طريق رسم خط على اليمين وخط في الأسفل. إذا
يضبط الكائن View
رسم NinePatch كخلفية له.
ومن ثم تحدد نص العرض، فإنه يتسع نفسه حتى
لا تشغل سوى المنطقة المحددة في السطرين اليمنى والسفلية (إذا تم تضمينها).
إذا لم يتم تضمين خطوط المساحة المتروكة، يستخدم Android السطرين الأيسر والعلوي من أجل
لتحديد هذه المنطقة القابلة للرسم.
لتوضيح الفرق بين الخطوط، تحدد الخطوط اليسرى والعلوية وحدات بكسل الصورة المسموح بنسخها من أجل تمديد . يحدد الخطان السفليان واليمينان المنطقة النسبية داخل الصورة يُسمح لمحتويات العرض بشغلها.
يوضح الشكل 1 مثالاً لرسم NinePatch يستخدم لتحديد زر:
يحدد رسم NinePatch هذا منطقة واحدة قابلة للتمدد يتم عرضها جهة اليسار والأعلى والخطوط والمنطقة القابلة للرسم بالخطوط السفلية واليمنى. في الصورة العلوية، تحدد الخطوط الرمادية المنقطة مناطق الصورة التي يتم نسخها من أجل توسيع الصورة. يحدد المستطيل الوردي في الصورة السفلية المنطقة التي يُسمح فيها بمحتوى العرض. إذا لم يكن المحتوى مناسبة لهذه المنطقة، ثم يتم تمديد الصورة لجعلها مناسبة.
تقدم أداة الرسم 9-التصحيح طريقة سهلة للغاية لإنشاء صور NinePatch باستخدام رسومات WYSIWYG المحرِّر. إنّها تحذّر أيضًا إذا كانت المنطقة التي تم تحديدها للّعبة القابلة للتمدّد المنطقة المعرّضة لخطر إنتاج عناصر رسم نتيجة لتوقُّع النسخ المتماثل.
يوضح نموذج XML التالي كيفية إضافة رسم NinePatch
إلى زرين. يتم حفظ صورة NinePatch في
res/drawable/my_button_background.9.png
<Button android:id="@+id/tiny" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerInParent="true" android:text="Tiny" android:textSize="8sp" android:background="@drawable/my_button_background"/> <Button android:id="@+id/big" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_centerInParent="true" android:text="Biiiiiiig text!" android:textSize="30sp" android:background="@drawable/my_button_background"/>
يُرجى العِلم أنّ سمتَي layout_width
وlayout_height
يتم ضبط السمات على wrap_content
حتى يكون الزر مناسبًا بدقة
حول النص.
يُظهر الشكل 2 الزرين المعروضين من صورة XML وNinePatch كما هو موضح أعلاه. لاحظ كيف يختلف عرض الزر وارتفاعه مع النص، وتمتد صورة الخلفية لتتلاءم معها.
عناصر مخصَّصة للرسم
عندما تريد إنشاء بعض الرسومات المخصّصة، يمكنك إجراء ذلك من خلال توسيع الفئة Drawable
(أو أي من فئاتها الفرعية).
وأهم طريقة للتنفيذ هي draw(Canvas)
.
لأنّ هذا الإجراء يوفّر الكائن Canvas
الذي يجب استخدامه لتقديمه
تعليمات الرسم.
يُظهر الرمز البرمجي التالي فئة فرعية بسيطة من Drawable
ترسم دائرة:
Kotlin
class MyDrawable : Drawable() { private val redPaint: Paint = Paint().apply { setARGB(255, 255, 0, 0) } override fun draw(canvas: Canvas) { // Get the drawable's bounds val width: Int = bounds.width() val height: Int = bounds.height() val radius: Float = Math.min(width, height).toFloat() / 2f // Draw a red circle in the center canvas.drawCircle((width / 2).toFloat(), (height / 2).toFloat(), radius, redPaint) } override fun setAlpha(alpha: Int) { // This method is required } override fun setColorFilter(colorFilter: ColorFilter?) { // This method is required } override fun getOpacity(): Int = // Must be PixelFormat.UNKNOWN, TRANSLUCENT, TRANSPARENT, or OPAQUE PixelFormat.OPAQUE }
Java
public class MyDrawable extends Drawable { private final Paint redPaint; public MyDrawable() { // Set up color and text size redPaint = new Paint(); redPaint.setARGB(255, 255, 0, 0); } @Override public void draw(Canvas canvas) { // Get the drawable's bounds int width = getBounds().width(); int height = getBounds().height(); float radius = Math.min(width, height) / 2; // Draw a red circle in the center canvas.drawCircle(width/2, height/2, radius, redPaint); } @Override public void setAlpha(int alpha) { // This method is required } @Override public void setColorFilter(ColorFilter colorFilter) { // This method is required } @Override public int getOpacity() { // Must be PixelFormat.UNKNOWN, TRANSLUCENT, TRANSPARENT, or OPAQUE return PixelFormat.OPAQUE; } }
بعد ذلك، يمكنك إضافة الرسم القابل للرسم في أي مكان تريده، مثل
ImageView
كما هو موضّح هنا:
Kotlin
val myDrawing = MyDrawable() val image: ImageView = findViewById(R.id.imageView) image.setImageDrawable(myDrawing) image.contentDescription = resources.getString(R.string.my_image_desc)
Java
MyDrawable mydrawing = new MyDrawable(); ImageView image = findViewById(R.id.imageView); image.setImageDrawable(mydrawing); image.setContentDescription(getResources().getString(R.string.my_image_desc));
في نظام التشغيل Android 7.0 (المستوى 24 لواجهة برمجة التطبيقات) والإصدارات الأحدث، يمكنك أيضًا تحديد نُسخ افتراضية مخصّصة للرسم. مع XML بالطرق التالية:
- استخدام اسم الفئة المؤهلة بالكامل كاسم لعنصر XML. بالنسبة لهذا النهج، يتم تخصيص
يجب أن تكون فئة قابلة للرسم فئة عامة عالية المستوى:
<com.myapp.MyDrawable xmlns:android="http://schemas.android.com/apk/res/android" android:color="#ffff0000" />
- استخدام
drawable
كاسم علامة XML وتحديد الفئة المؤهلة بالكامل من تصنيف الفئة. يمكن استخدام هذا النهج لكل من صفوف المستوى الأعلى العامة الفئات الداخلية الثابتة العامة:<drawable xmlns:android="http://schemas.android.com/apk/res/android" class="com.myapp.MyTopLevelClass$MyDrawable" android:color="#ffff0000" />
إضافة درجة اللون إلى العناصر القابلة للرسم
من خلال الإصدار Android 5.0 (المستوى 21 لواجهة برمجة التطبيقات) والإصدارات الأحدث، يمكنك تلوين الصور النقطية وتسع تصحيحات
أقنعة ألفا. يمكنك تلوينها باستخدام موارد الألوان أو سمات المظاهر التي تتغيّر إلى اللون.
الموارد (على سبيل المثال، ?android:attr/colorPrimary
). في العادة، تُنشئ مواد العرض هذه
مرة واحدة فقط وقم بتلوينها تلقائيًا لتلائم مظهرك.
يمكنك تطبيق تلوين خفيف على BitmapDrawable
أو NinePatchDrawable
أو VectorDrawable
.
باستخدام الطريقة setTint()
. يمكنك
أيضًا ضبط لون درجة اللون ووضعها في التنسيقات باستخدام android:tint
android:tintMode
سمة.
استخراج الألوان البارزة من صورة
تحتوي مكتبة دعم Android على فئة Palette
التي تتيح لك استخراج الألوان البارزة من صورة.
يمكنك تحميل عناصرك القابلة للرسم على أنّها Bitmap
وتمريرها إلى Palette
للوصول إلى ألوانها.
لمزيد من المعلومات، يُرجى قراءة المقالة تحديد الألوان باستخدام
واجهة برمجة التطبيقات Palette API