التنسيقات في طرق العرض
يحدِّد التنسيق بنية واجهة المستخدم في تطبيقك، كما هو الحال في نشاط. ويتم إنشاء جميع العناصر في
التنسيق باستخدام تدرج هرمي لكائن
View
وViewGroup
. ترسم View
عادةً شيئًا يمكن للمستخدم رؤيته والتفاعل معه. ViewGroup
هي حاوية غير مرئية تحدّد بنية التنسيق لـ View
وكائنات ViewGroup
الأخرى، كما هو موضّح في الشكل 1.
![](https://developer.android.com/static/images/viewgroup_2x.png?authuser=3&hl=ar)
يُطلق غالبًا على كائنات View
اسم التطبيقات المصغّرة، ويمكن أن تكون إحدى الفئات الفرعية العديدة، مثل Button
أو TextView
. يُطلق عادةً على
كائنات ViewGroup
اسم التنسيقات، وقد تكون نوعًا من الأنواع المتعددة التي توفّر بنية تنسيق مختلفة، مثل LinearLayout
أو
ConstraintLayout
.
يمكنك الإعلان عن تنسيق بطريقتين:
- توضيح عناصر واجهة المستخدم في ملف XML: يوفّر Android مفردات XML واضحة تتوافق مع فئات
View
وفئاتها الفرعية، مثل فئات التطبيقات المصغّرة والتنسيقات. يمكنك أيضًا استخدام محرِّر التنسيق في "استوديو Android" لإنشاء تنسيق XML باستخدام واجهة السحب والإفلات. - إنشاء مثيل لعناصر التنسيق في وقت التشغيل يمكن لتطبيقك إنشاء العنصرَين
View
وViewGroup
ومعالجة خصائصهما آليًا.
يتيح لك تعريف واجهة المستخدم بتنسيق XML فصل طريقة عرض تطبيقك عن الرمز الذي يتحكم في سلوكه. يسهّل استخدام ملفات XML أيضًا توفير تخطيطات مختلفة لأحجام الشاشة والاتجاهات المختلفة. وقد تم تناول ذلك بالتفصيل في مقالة إتاحة أحجام الشاشة المختلفة.
يمنحك إطار عمل Android المرونة في استخدام إحدى هاتين الطريقتين أو كلتيهما لإنشاء واجهة المستخدم لتطبيقك. على سبيل المثال، يمكنك الإفصاح عن التنسيقات التلقائية لتطبيقك بتنسيق XML، ثم تعديل التنسيق في وقت التشغيل.
كتابة ملف XML
باستخدام مفردات XML الخاصة بنظام التشغيل Android، يمكنك تصميم تنسيقات واجهة المستخدم وعناصر الشاشة التي تحتوي عليها بسرعة، بالطريقة نفسها التي تنشئ بها صفحات ويب بتنسيق HTML باستخدام سلسلة من العناصر المتداخلة.
يجب أن يحتوي كل ملف تنسيق على عنصر جذر واحد بالضبط، والذي يجب أن يكون كائن View
أو ViewGroup
. بعد تحديد العنصر الجذر، يمكنك إضافة عناصر تنسيق أو تطبيقات مصغّرة إضافية كعناصر فرعية لإنشاء تسلسل هرمي View
يحدّد التنسيق تدريجيًا. على سبيل المثال، إليك تنسيق XML يستخدم LinearLayout
عمودي للاحتفاظ بالسمتَين TextView
وButton
:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello, I am a TextView" /> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello, I am a Button" /> </LinearLayout>
بعد تعريف التنسيق بتنسيق XML، احفظ الملف بالامتداد .xml
في دليل res/layout/
الخاص بمشروع Android حتى يتم تجميعه بشكل صحيح.
لمزيد من المعلومات عن بنية ملف XML للتنسيق، يُرجى الاطّلاع على مورد التنسيق.
تحميل مورد XML
عند تجميع تطبيقك، يتم تجميع كل ملف بتنسيق XML في مورد View
. حمِّل مورد التنسيق في
Activity.onCreate()
تنفيذ معاودة الاتصال لتطبيقك. يمكنك إجراء ذلك من خلال طلب
"setContentView()
"،
وإرساله المرجع إلى مورد التنسيق في النموذج:
R.layout.layout_file_name
. على سبيل المثال، إذا تم حفظ تنسيق XML بتنسيق main_layout.xml
، يمكنك تحميله على Activity
على النحو التالي:
Kotlin
fun onCreate(savedInstanceState: Bundle) { super.onCreate(savedInstanceState) setContentView(R.layout.main_layout) }
Java
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main_layout); }
يستدعي إطار عمل Android طريقة استدعاء onCreate()
في Activity
عند تشغيل Activity
. لمزيد من المعلومات حول دورات حياة الأنشطة، راجع مقدمة في
الأنشطة.
السمات
يتيح كل عنصر من كائنات View
وViewGroup
استخدام مجموعة
متنوعة من سمات XML. تكون بعض السمات خاصة بكائن View
. على سبيل المثال، يتوافق TextView
مع السمة textSize
. ومع ذلك، يتم اكتساب هذه السمات أيضًا من خلال أي كائنات View
تعمل على توسيع هذه الفئة. وبعضها شائع في جميع كائنات View
لأنّها مكتسبة من الفئة View
الجذر، مثل السمة id
. وتُعتبر السمات الأخرى مَعلَمات
تنسيق، وهي سمات تصف اتجاهات تنسيق معيّنة
للكائن View
، على النحو الذي يحدّده الكائن الرئيسي
ViewGroup
لهذا العنصر.
رقم التعريف
يمكن أن يحتوي أي عنصر View
على رقم تعريف عدد صحيح مرتبط به لتحديد View
بشكل فريد ضمن العرض التدرّجي. عندما يتم تجميع التطبيق، تتم الإشارة إلى هذا المعرّف كعدد صحيح، ولكن يتم عادةً تخصيص المعرّف في ملف XML للتنسيق كسلسلة في السمة id
. وهذه سمة XML مشتركة بين جميع كائنات View
، ويتم تحديدها من خلال الفئة View
. أنت تستخدمه كثيرًا. تكون صيغة المعرف داخل علامة XML على النحو التالي:
android:id="@+id/my_button"
يشير الرمز at (@) في بداية السلسلة إلى أنّ محلل XML يحلل بقية سلسلة المعرّف ويوسّعها ويحدّدها كمورد للمعرّف. يعني رمز الجمع (+) أن هذا اسم مورد جديد يجب إنشاؤه وإضافته إلى مواردك في ملف R.java
.
يوفّر إطار عمل Android العديد من موارد المعرّفات الأخرى. عند الإشارة إلى معرّف مورد Android، لا تحتاج إلى رمز الجمع، ولكن عليك إضافة مساحة اسم الحزمة android
على النحو التالي:
android:id="@android:id/empty"
تشير مساحة اسم الحزمة android
إلى أنّك تُشير إلى رقم تعريف من فئة موارد android.R
، بدلاً من فئة الموارد المحلية.
لإنشاء طرق عرض والرجوع إليها من تطبيقك، يمكنك استخدام نمط شائع على النحو التالي:
- حدِّد ملفًا شخصيًا في ملف التنسيق وخصِّص له معرّفًا فريدًا، كما في المثال التالي:
<Button android:id="@+id/my_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/my_button_text"/>
- أنشئ مثيلاً لعنصر العرض واحتفِظ به من التنسيق،
عادةً باستخدام
onCreate()
، كما هو موضّح في المثال التالي:Kotlin
val myButton: Button = findViewById(R.id.my_button)
Java
Button myButton = (Button) findViewById(R.id.my_button);
من المهم تحديد أرقام التعريف لعناصر الملف الشخصي عند إنشاء RelativeLayout
.
في التنسيق النسبي، يمكن أن تحدد طرق العرض التابعة تنسيقها بالنسبة إلى طريقة العرض التابعة الأخرى، والتي تتم الإشارة إليها بواسطة المعرف الفريد.
لا يلزم أن يكون المعرف فريدًا عبر الشجرة بالكامل، ولكن يجب أن يكون فريدًا داخل الجزء الذي تبحث عنه في الشجرة. قد تكون غالبًا الشجرة بأكملها، لذلك من الأفضل أن تجعلها فريدة عندما يكون ذلك ممكنًا.
معلمات التنسيق
تحدّد سمات تنسيق XML المسماة layout_something
معلَمات تنسيق للسمة View
المناسبة
للسمة ViewGroup
المتوفّرة فيها.
تنفِّذ كل فئة ViewGroup
فئة مدمَجة تمتد إلى ViewGroup.LayoutParams
.
وتضم هذه الفئة الفرعية أنواع الخصائص التي تحدد حجم وموضع كل ملف شخصي فرعي، حسبما يتناسب مع مجموعة الملفات الشخصية. وكما هو موضّح في الشكل 2، تحدِّد مجموعة طرق العرض الرئيسية معلَمات التنسيق لكل طريقة عرض فرعية، بما في ذلك مجموعة طرق العرض الفرعية.
![](https://developer.android.com/static/images/layoutparams.png?authuser=3&hl=ar)
لكل فئة فرعية في LayoutParams
بنية خاصة بها لضبط القيم. ويجب أن يحدّد كل عنصر فرعي قيمة LayoutParams
مناسبة للعنصر الرئيسي، ولكن قد تحدّد أيضًا قيمة
LayoutParams
مختلفة لعناصره الثانوية.
تشمل جميع مجموعات طرق العرض عرضًا وارتفاعًا، باستخدام layout_width
وlayout_height
، ويجب تحديدهما في كل طريقة عرض. يتضمن العديد من
LayoutParams
هوامش وحدود اختيارية.
يمكنك تحديد العرض والارتفاع باستخدام القياسات الدقيقة، ولكنك قد لا ترغب في إجراء ذلك كثيرًا. في كثير من الأحيان، يمكنك استخدام أحد هذه الثوابت لتعيين العرض أو الارتفاع:
wrap_content
: يقيّم هذا السمة طريقة العرض بما يتناسب مع الحجم نفسه للأبعاد التي يتطلبها المحتوى.match_parent
: يعبّر هذا المقياس عن حجم المشاهدة بقدر ما تسمح به مجموعة المشاهدات الرئيسية.
وبشكل عام، لا ننصح بتحديد عرض التنسيق وارتفاعه باستخدام الوحدات المطلقة مثل وحدات البكسل. هناك نهج أفضل وهو استخدام القياسات النسبية، مثل وحدات البكسل المستقلة الكثافة (dp) أو wrap_content
أو
match_parent
، لأنّها تساعد تطبيقك على العرض بشكل سليم على مستوى مجموعة متنوعة من أحجام شاشات الأجهزة. يتم تحديد أنواع القياس المقبولة في
مورد التنسيق.
موضع التصميم
طريقة العرض بأشكال هندسية مستطيلة. ويكون له موقع، ويتم التعبير عنه كزوج من الإحداثيات لليسار والأعلى وأبعاده، ويتم التعبير عنها بالعرض والارتفاع. وحدة الموقع والأبعاد هي البكسل.
يمكنك استرداد موقع العرض من خلال استدعاء الطريقتين
getLeft()
و
getTop()
.
تعرض القيمة الأولى الإحداثي الأيسر (x) للمستطيل الذي يمثّل طريقة العرض. ويعرض الإصدار الأخير الإحداثي العلوي (y) للمستطيل
الذي يمثّل طريقة العرض. تعرض هذه الطرق موقع العرض نسبةً إلى الأصل. على سبيل المثال، عندما تعرض الدالة getLeft()
القيمة 20، هذا يعني أنّ طريقة العرض تقع على بُعد 20 بكسل على يمين الحافة اليسرى للشاشة الرئيسية المباشرة.
بالإضافة إلى ذلك، هناك طرق ملائمة لتجنُّب العمليات الحسابية غير الضرورية، وهي:
getRight()
وgetBottom()
.
تعرض هذه الطرق إحداثيات الحافتين اليمنى والسفلية للمستطيل التي تمثل العرض. على سبيل المثال، يشبه استدعاء getRight()
عملية المعالجة التالية: getLeft() + getWidth()
.
الحجم والمساحة المتروكة والهوامش
يتم التعبير عن حجم طريقة العرض من خلال العرض والارتفاع. تحتوي طريقة العرض على زوجين من قيم العرض والارتفاع.
يُعرف الزوج الأول باسم العرض الذي تم قياسه والارتفاع الذي تم قياسه. وتحدد هذه الأبعاد مدى تكبير العرض
ضمن الأصل. يمكنك الحصول على السمات التي تم قياسها من خلال استدعاء
getMeasuredWidth()
وgetMeasuredHeight()
.
يُعرف الزوج الثاني باسم width وheight أو أحيانًا
رسم العرض ورسم الارتفاع. تحدد هذه الأبعاد الحجم الفعلي للعرض على الشاشة، في وقت الرسم وبعد التخطيط. قد تختلف هذه القيم، ولكن لا ينبغي ذلك، عن العرض والارتفاع الذين تم قياسهم. ويمكنك الحصول على العرض والارتفاع عن طريق استدعاء getWidth()
وgetHeight()
.
لقياس أبعاده، تأخذ طريقة العرض في الاعتبار المساحة المتروكة الخاصة بها. يتم التعبير عن المساحة المتروكة بالبكسل للأجزاء اليسرى والعلوية واليمنى والسفلية من العرض.
يمكنك استخدام المساحة المتروكة لمعادلة محتوى العرض بعدد معيّن من وحدات البكسل. على سبيل المثال، تؤدي المساحة المتروكة اليسرى المكونة من اثنتين إلى دفع محتوى العرض ببكسلتين
إلى يمين الحافة اليسرى. يمكنك ضبط المساحة المتروكة باستخدام الطريقة
setPadding(int, int, int, int)
وإجراء طلب بحث عنها من خلال استدعاء
getPaddingLeft()
وgetPaddingTop()
وgetPaddingRight()
وgetPaddingBottom()
.
على الرغم من أن طريقة العرض يمكنها تحديد مساحة متروكة، إلا أنها لا تدعم الهوامش. ومع ذلك، تدعم مجموعات
العرض الهوامش. يمكنك الاطّلاع على ViewGroup
وViewGroup.MarginLayoutParams
للحصول على مزيد من المعلومات.
لمزيد من المعلومات عن السمات، يُرجى الاطّلاع على مقالة السمة.
بالإضافة إلى إعداد الهوامش والمساحة المتروكة آليًا، يمكنك أيضًا ضبطها في تنسيقات XML، كما هو موضّح في المثال التالي:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="16dp" android:padding="8dp" android:text="Hello, I am a TextView" /> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="16dp" android:paddingBottom="4dp" android:paddingEnd="8dp" android:paddingStart="8dp" android:paddingTop="4dp" android:text="Hello, I am a Button" /> </LinearLayout>
يوضح المثال السابق الهامش والمساحة المتروكة قيد تطبيق. يتضمّن TextView
هوامش موحّدة ومساحة متروكة مطبَّقة في كل مكان، ويعرض Button
كيفية تطبيقها بشكل مستقل على حواف مختلفة.
التخطيطات الشائعة
توفر كل فئة فرعية من الفئة ViewGroup
طريقة فريدة لعرض طرق العرض التي تدمجها فيها. إنّ نوع التنسيق الأكثر مرونة هو
"ConstraintLayout
" الذي يوفّر أفضل الأدوات للحفاظ على سطحية التدرّج الهرمي للتصميم.
فيما يلي بعض أنواع التخطيط الشائعة المضمنة في نظام Android الأساسي.
![](https://developer.android.com/static/images/ui/linearlayout-small.png?authuser=3&hl=ar)
تنظّم العناصر الثانوية في صف أفقي أو عمودي واحد وتنشئ شريط تمرير إذا تجاوز طول النافذة طول الشاشة.
إنشاء قوائم ديناميكية
عندما يكون محتوى التنسيق ديناميكيًا أو غير محدَّد مسبقًا، يمكنك استخدام RecyclerView
أو فئة فرعية من AdapterView
.
بشكل عام، يكون RecyclerView
الخيار الأفضل لأنّه يستخدم
الذاكرة بكفاءة أكبر من AdapterView
.
تتضمّن التنسيقات الشائعة التي يمكن استخدامها مع RecyclerView
وAdapterView
ما يلي:
يوفر RecyclerView
المزيد من الاحتمالات وخيار
إنشاء مدير
تخطيط مخصص.
ملء عرض المحوّل بالبيانات
يمكنك تعبئة AdapterView
مثل ListView
أو
GridView
من خلال
ربط مثيل AdapterView
بـ
Adapter
،
الذي يسترجع البيانات من مصدر خارجي وينشئ View
يمثّل كل إدخال بيانات.
يوفّر Android عدة فئات فرعية من Adapter
مفيدة لاسترداد أنواع البيانات المختلفة وإنشاء طرق عرض لـ AdapterView
. المحولان الأكثر شيوعًا هما:
ArrayAdapter
- استخدِم هذا المحوّل عندما يكون مصدر البيانات مصفوفة. ينشئ
ArrayAdapter
تلقائيًا طريقة عرض لكل عنصر مصفوفة من خلال استدعاءtoString()
في كل عنصر ووضع المحتوى فيTextView
.على سبيل المثال، إذا كان لديك مصفوفة من السلاسل تريد عرضها في
ListView
، عليك إعدادArrayAdapter
جديدة باستخدام دالة إنشاء لتحديد تنسيق كل سلسلة ومصفوفة السلسلة:Kotlin
val adapter = ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, myStringArray)
Java
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, myStringArray);
في ما يلي وسيطات الدالة الإنشائية هذه:
- تطبيقك
Context
- التنسيق الذي يحتوي على
TextView
لكل سلسلة في المصفوفة - صفيف السلسلة
بعد ذلك، يمكنك الاتصال برقم
setAdapter()
علىListView
:Kotlin
val listView: ListView = findViewById(R.id.listview) listView.adapter = adapter
Java
ListView listView = (ListView) findViewById(R.id.listview); listView.setAdapter(adapter);
لتخصيص مظهر كل عنصر، يمكنك إلغاء الطريقة
toString()
للكائنات في المصفوفة. ولإنشاء طريقة عرض لكل عنصر بخلاف السمةTextView
، على سبيل المثال، إذا أردت عرض السمةImageView
لكل عنصر في مصفوفة، يمكنك تمديد الفئةArrayAdapter
وإلغاءgetView()
لعرض نوع العرض الذي تريده لكل عنصر. - تطبيقك
SimpleCursorAdapter
- استخدِم هذا المحوّل عندما تأتي بياناتك من
Cursor
. عند استخدامSimpleCursorAdapter
، حدِّد تنسيقًا لاستخدامه مع كل صف فيCursor
والأعمدة فيCursor
التي تريد إدراجها في طرق عرض التنسيق المطلوب. على سبيل المثال، إذا أردت إنشاء قائمة بأسماء الأشخاص وأرقام هواتفهم، يمكنك تنفيذ طلب بحث يعرضCursor
يحتوي على صف لكل شخص وأعمدة للأسماء والأرقام. ويمكنك بعد ذلك إنشاء مصفوفة سلسلة وتحدّد الأعمدة منCursor
التي تريدها في التنسيق لكل نتيجة ومصفوفة عدد صحيح تحدِّد طرق العرض المقابلة التي يجب وضع كل عمود فيها:Kotlin
val fromColumns = arrayOf(ContactsContract.Data.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER) val toViews = intArrayOf(R.id.display_name, R.id.phone_number)
Java
String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER}; int[] toViews = {R.id.display_name, R.id.phone_number};
عند إنشاء مثيل لـ
SimpleCursorAdapter
، عليك ضبط التنسيق لاستخدامه مع كل نتيجة وCursor
الذي يحتوي على النتائج وهاتَين الصفيفتَين:Kotlin
val adapter = SimpleCursorAdapter(this, R.layout.person_name_and_number, cursor, fromColumns, toViews, 0) val listView = getListView() listView.adapter = adapter
Java
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.person_name_and_number, cursor, fromColumns, toViews, 0); ListView listView = getListView(); listView.setAdapter(adapter);
تنشئ
SimpleCursorAdapter
بعد ذلك طريقة عرض لكل صف فيCursor
باستخدام التنسيق المتوفر من خلال إدراج كل عنصرfromColumns
في طريقة عرضtoViews
المقابلة.
إذا غيّرت البيانات الأساسية التي
يقرأها المحوّل على مدار عمر التطبيق، اتصل بالرقم
notifyDataSetChanged()
.
يؤدي ذلك إلى إعلام العرض المرفق بأن البيانات قد تم تغييرها وتتم إعادة تحميلها.
التعامل مع الأحداث الناتجة عن النقر
يمكنك الاستجابة لأحداث النقر على كل عنصر في AdapterView
من خلال تنفيذ واجهة
AdapterView.OnItemClickListener
. على سبيل المثال:
Kotlin
listView.onItemClickListener = AdapterView.OnItemClickListener { parent, view, position, id -> // Do something in response to the click. }
Java
// Create a message handling object as an anonymous class. private OnItemClickListener messageClickedHandler = new OnItemClickListener() { public void onItemClick(AdapterView parent, View v, int position, long id) { // Do something in response to the click. } }; listView.setOnItemClickListener(messageClickedHandler);
مصادر إضافية
تعرّف على كيفية استخدام التخطيطات في تطبيق Sunflower التجريبي على GitHub.