التنسيقات في طرق العرض
يحدّد التنسيق بنية واجهة المستخدم في تطبيقك، كما هو الحال في
نشاط. يتم إنشاء جميع العناصر في
التصميم باستخدام تسلسل هرمي من
كائنات View
وViewGroup
. يرسم عادةً View
شيئًا يمكن للمستخدم
رؤيته والتفاعل معه. ViewGroup
هي حاوية غير مرئية تحدّد بنية تنسيق View
وكائنات ViewGroup
الأخرى، كما هو موضّح في الشكل 1.
غالبًا ما يُطلق على كائنات 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، تحدد مجموعة طرق العرض الرئيسية معلمات التنسيق لكل طريقة عرض فرعية، بما في ذلك مجموعة طرق العرض الفرعية.
لكل فئة فرعية 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 الأساسي.
ينظّم عناصره الثانوية في صف أفقي أو عمودي واحد وينشئ شريط تمرير إذا كان طول النافذة يتجاوز طول الشاشة.
إنشاء قوائم ديناميكية
عندما يكون محتوى تنسيقك ديناميكيًا أو غير محدَّد مسبقًا، يمكنك
استخدام
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.