القوائم هي عنصر واجهة مستخدم شائع في العديد من أنواع التطبيقات. ولتقديم تجربة مستخدم مألوفة ومتسقة، استخدِم واجهات برمجة تطبيقات "Menu
" لعرض إجراءات المستخدمين وخيارات أخرى في أنشطتك.
يوضح هذا المستند كيفية إنشاء الأنواع الأساسية الثلاثة من القوائم أو العروض التقديمية للإجراءات على جميع إصدارات Android:
- قائمة الخيارات وشريط التطبيقات
- قائمة الخيارات هي المجموعة الأساسية من العناصر في
القائمة لأحد الأنشطة. ويمكنك من خلاله وضع الإجراءات التي لها تأثير عام في التطبيق، مثل "بحث" و"إنشاء رسالة إلكترونية" و"الإعدادات".
راجِع القسم إنشاء قائمة خيارات.
- قائمة السياقات ووضع الإجراءات المستندة إلى السياق
- قائمة السياقات هي قائمة عائمة
تظهر عندما ينقر المستخدم مع الاستمرار على أحد العناصر. وهي توفّر إجراءات تؤثر في المحتوى أو إطار السياق المحدّدَين.
يعرض وضع الإجراءات المستندة إلى السياق بنود العمل التي تؤثر في المحتوى المحدّد في شريط أعلى الشاشة ويسمح للمستخدم باختيار عناصر متعددة.
راجِع قسم إنشاء قائمة سياقية.
- القائمة المنبثقة
- تعرض قائمة منبثقة قائمة عمودية بالعناصر الثابتة بطريقة العرض التي تستدعي القائمة. ويفيد هذا الإجراء توفير مجموعة كبيرة من الإجراءات
المتعلّقة بمحتوى معيّن أو لتوفير خيارات للجزء الثاني من الأمر. ولا تؤثر الإجراءات التي يتم تنفيذها في القائمة المنبثقة مباشرةً في
المحتوى ذي الصلة، ويتم استخدام تلك الإجراءات في السياق. إنّ القائمة المنبثقة مخصّصة للإجراءات الموسّعة التي تتعلّق بمناطق المحتوى في نشاطك.
راجِع القسم إنشاء قائمة منبثقة.
تحديد قائمة في ملف XML
بالنسبة إلى جميع أنواع القوائم، يوفر Android تنسيق XML قياسيًا لتحديد عناصر القائمة. بدلاً من إنشاء قائمة في رمز النشاط، حدِّد قائمة وكل عناصرها في مورد قائمة بتنسيق XML. ويمكنك بعد ذلك تضخيم مورد القائمة من خلال تحميله ككائن Menu
في نشاطك أو الجزء.
يعد استخدام مورد قائمة ممارسة جيدة للأسباب التالية:
- من الأسهل الاطّلاع على بنية القائمة في ملف XML.
- تعمل هذه الميزة على فصل محتوى القائمة عن رمز السلوك في تطبيقك.
- يتيح لك هذا النظام إنشاء إعدادات قوائم بديلة لمختلف إصدارات الأنظمة الأساسية وأحجام الشاشات وعمليات ضبط أخرى من خلال الاستفادة من إطار عمل موارد التطبيقات.
لتحديد قائمة، أنشِئ ملف XML داخل دليل res/menu/
الخاص بمشروعك وأنشِئ القائمة باستخدام العناصر التالية:
<menu>
- تعرّف على
Menu
، وهي حاوية لعناصر القائمة. ويجب أن يكون العنصر<menu>
هو العقدة الجذرية للملف، ويمكن أن يتضمّن عنصرًا واحدًا أو أكثر من عناصر<item>
و<group>
. <item>
- تنشئ
MenuItem
، والتي تمثل عنصرًا واحدًا في قائمة. ويمكن أن يحتوي هذا العنصر على عنصر<menu>
مدمج لإنشاء قائمة فرعية. <group>
- هي حاوية اختيارية غير مرئية لعناصر
<item>
. وتتيح لك أيضًا تصنيف عناصر القائمة لكي تشارك السمات، مثل الحالة النشطة وإذن الوصول. لمزيد من المعلومات، راجِع القسم إنشاء مجموعة قوائم.
إليك مثال على قائمة باسم game_menu.xml
:
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/new_game" android:icon="@drawable/ic_new_game" android:title="@string/new_game" app:showAsAction="ifRoom"/> <item android:id="@+id/help" android:icon="@drawable/ic_help" android:title="@string/help" /> </menu>
يتيح العنصر <item>
استخدام عدة سمات يمكنك استخدامها لتحديد مظهر العنصر وسلوكه. تتضمن العناصر في القائمة السابقة
السمات التالية:
android:id
- معرّف مورد فريد للعنصر، ما يتيح للتطبيق التعرّف على العنصر عندما يختاره المستخدم.
android:icon
- إشارة إلى عنصر قابل للرسم لاستخدامه كرمز للعنصر.
android:title
- إشارة إلى سلسلة لاستخدامها كعنوان للعنصر.
android:showAsAction
- مواصفات وقت ظهور هذا العنصر كبند عمل وطريقة ظهوره كبند عمل في شريط التطبيقات
هذه هي أهم السمات التي تستخدمها، ولكن هناك المزيد من السمات المتاحة. للحصول على معلومات حول جميع السمات المتوافقة، يمكنك الاطّلاع على مستندات مورد القائمة.
يمكنك إضافة قائمة فرعية إلى عنصر في أي قائمة من خلال إضافة عنصر <menu>
كعنصر ثانوي في <item>
.
تكون القوائم الفرعية مفيدة عندما يحتوي تطبيقك على الكثير من الوظائف التي يمكن تنظيمها حسب المواضيع، مثل العناصر في شريط القوائم في تطبيق الكمبيوتر الشخصي، مثل ملف وتعديل وعرض. اطّلِع على المثال التالي:
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/file" android:title="@string/file" > <!-- "file" submenu --> <menu> <item android:id="@+id/create_new" android:title="@string/create_new" /> <item android:id="@+id/open" android:title="@string/open" /> </menu> </item> </menu>
لاستخدام القائمة في نشاطك، عليك _inflate_ مورد القائمة، وتحويل مورد XML إلى كائن قابل للبرمجة باستخدام MenuInflater.inflate()
.
توضّح الأقسام التالية كيفية تضخيم قائمة كل نوع من أنواع القوائم.
إنشاء قائمة خيارات
قائمة الخيارات، مثل القائمة التي تظهر في الشكل 1، هي المكان الذي تقوم فيه بتضمين الإجراءات والخيارات الأخرى ذات الصلة بسياق النشاط الحالي، مثل "بحث" و"إنشاء رسالة إلكترونية" و "الإعدادات".
![صورة تعرض شريط التطبيقات الخاص بتطبيق "جداول بيانات Google"](https://developer.android.com/static/images/training/appbar/appbar_sheets_2x.png?authuser=3&hl=ar)
يمكنك الإعلان عن عناصر لقائمة الخيارات من
فئتك الفرعية
Activity
أو من
فئتك الفرعية Fragment
. إذا كان كل من نشاطك وأجزائك تشير إلى عناصر في قائمة الخيارات، سيتم دمج العناصر في واجهة المستخدم. تظهر عناصر النشاط أولاً، تليها عناصر كل جزء، بالترتيب الذي تتم إضافة الأجزاء
به إلى النشاط. إذا لزم الأمر، يمكنك إعادة ترتيب الأصناف في القائمة باستخدام
السمة android:orderInCategory
في كل
<item>
تحتاج إلى نقله.
لتحديد قائمة الخيارات لأحد الأنشطة، يمكنك إلغاء
onCreateOptionsMenu()
.
توفّر الأجزاء معاودة الاتصال
onCreateOptionsMenu()
الخاصة بها. بهذه الطريقة، يمكنك تضخيم مورد القائمة،
المحدّد في XML، إلى Menu
الوارد في
معاودة الاتصال. يظهر ذلك في المثال التالي:
Kotlin
override fun onCreateOptionsMenu(menu: Menu): Boolean { val inflater: MenuInflater = menuInflater inflater.inflate(R.menu.game_menu, menu) return true }
Java
@Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.game_menu, menu); return true; }
يمكنك أيضًا إضافة عناصر في القائمة باستخدام add()
واسترداد العناصر باستخدام
findItem()
لمراجعة خصائصها باستخدام واجهات برمجة تطبيقات MenuItem
.
التعامل مع الأحداث الناتجة عن النقر
عندما يختار المستخدم عنصرًا من قائمة الخيارات، بما في ذلك بنود العمل
في شريط التطبيق، يستدعي النظام
طريقة
onOptionsItemSelected()
نشاطك. تنجح هذه الطريقة في اجتياز MenuItem
المحدّدة. يمكنك تحديد العنصر من خلال استدعاء
getItemId()
،
الذي يعرض المعرّف الفريد للعنصر في القائمة، والمحدّد من خلال السمة
android:id
في مورد القائمة أو من خلال عدد صحيح مخصّص
للطريقة add()
. يمكنك مطابقة هذا المعرف مع عناصر
القائمة المعروفة لتنفيذ الإجراء المناسب.
Kotlin
override fun onOptionsItemSelected(item: MenuItem): Boolean { // Handle item selection. return when (item.itemId) { R.id.new_game -> { newGame() true } R.id.help -> { showHelp() true } else -> super.onOptionsItemSelected(item) } }
Java
@Override public boolean onOptionsItemSelected(MenuItem item) { // Handle item selection. switch (item.getItemId()) { case R.id.new_game: newGame(); return true; case R.id.help: showHelp(); return true; default: return super.onOptionsItemSelected(item); } }
عندما تتم معالجة عنصر في القائمة بنجاح، يمكنك إرجاع true
. إذا لم تتعامل مع عنصر القائمة، عليك استدعاء التنفيذ المميز لـ
onOptionsItemSelected()
. يُرجع التنفيذ الافتراضي
خطأ.
إذا كان نشاطك يتضمّن أجزاءً، يستدعي النظام أولاً
onOptionsItemSelected()
للنشاط، ثم يستدعي كل جزء
بترتيب إضافة الأجزاء، حتى يعرض الجزء true
أو
يتم استدعاء جميع الأجزاء.
تغيير عناصر القائمة في وقت التشغيل
بعد استدعاء النظام onCreateOptionsMenu()
، يحتفظ
بنسخة Menu
التي تمت تعبئتها ولا يطلب
onCreateOptionsMenu()
مرة أخرى ما لم يتم إيقاف القائمة.
ومع ذلك، يمكنك استخدام onCreateOptionsMenu()
فقط لإنشاء حالة القائمة
الأولية وعدم إجراء تغييرات أثناء دورة نشاط النشاط.
إذا أردت تعديل قائمة الخيارات استنادًا إلى الأحداث التي تقع خلال
دورة النشاط، يمكنك إجراء ذلك في
الطريقة
onPrepareOptionsMenu()
. تنقلك هذه الطريقة العنصر Menu
كما هو
حاليًا حتى تتمكن من تعديله، مثل إضافة عناصر أو إزالتها أو إيقافها.
توفّر الأجزاء أيضًا
onPrepareOptionsMenu()
معاودة الاتصال.
تُعد قائمة الخيارات مفتوحة دائمًا عند عرض عناصر
القائمة في شريط التطبيقات. عند وقوع حدث وتريد إجراء تعديل على القائمة، يمكنك استدعاء
invalidateOptionsMenu()
لطلب استدعاء النظام لـ onPrepareOptionsMenu()
.
إنشاء قائمة سياقية
![صورة تعرض قائمة سياقات عائمة](https://developer.android.com/static/develop/ui/views/images/context_menu_no_icons.png?authuser=3&hl=ar)
توفر القائمة السياقية إجراءات تؤثر على عنصر أو إطار
سياق معين في واجهة المستخدم. يمكنك توفير قائمة سياقات لأي طريقة عرض، إلا أنها تُستخدم غالبًا
لعناصر في RecylerView
أو
مجموعات طرق عرض أخرى يمكن للمستخدم من خلالها تنفيذ إجراءات مباشرة على كل
عنصر.
هناك طريقتان لتقديم الإجراءات المستندة إلى السياق:
- في قائمة سياق عائمة تظهر قائمة كقائمة عائمة لعناصر القائمة، على غرار مربّع الحوار، عندما يضغط المستخدم مع الاستمرار على طريقة عرض تشير إلى إتاحة قائمة سياق. ويمكن للمستخدمين تنفيذ إجراء مستند إلى السياق على عنصر واحد في كل مرة.
- في وضع الإجراء المستند إلى السياق هذا الوضع هو تطبيق من أنظمة
ActionMode
يعرض شريط إجراءات سياقية أو CAB أعلى الشاشة مع بنود العمل التي تؤثر في العناصر المحددة. عند تفعيل هذا الوضع، يمكن للمستخدمين تنفيذ إجراء على عناصر متعددة في آنٍ واحد، إذا كان تطبيقك يتيح ذلك.
ملاحظة: لا تتيح قائمة السياقات استخدام اختصارات العناصر ورموز العناصر.
إنشاء قائمة سياق عائمة
لتوفير قائمة سياق عائمة، اتّبِع الخطوات التالية:
- يمكنك تسجيل
View
الذي ترتبط به قائمة السياق من خلال استدعاءregisterForContextMenu()
وتمريره إلىView
.إذا كان نشاطك يستخدم
RecyclerView
وأردت أن يوفّر كل عنصر قائمة السياقات نفسها، يمكنك تسجيل كل العناصر للحصول على قائمة سياقات من خلال تمريرRecyclerView
إلىregisterForContextMenu()
. - نفِّذ الطريقة
onCreateContextMenu()
فيActivity
أوFragment
.عندما تتلقّى طريقة العرض المسجَّلة حدث اللمس مع الاستمرار، يطلب النظام طريقة
onCreateContextMenu()
. يمكنك هنا تحديد عناصر القائمة، عادةً من خلال تضخيم مورد القائمة، كما في المثال التالي:Kotlin
override fun onCreateContextMenu(menu: ContextMenu, v: View, menuInfo: ContextMenu.ContextMenuInfo) { super.onCreateContextMenu(menu, v, menuInfo) val inflater: MenuInflater = menuInflater inflater.inflate(R.menu.context_menu, menu) }
Java
@Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.context_menu, menu); }
تتيح لك السمة
MenuInflater
تضخيم قائمة السياقات من أحد موارد القوائم. تشمل مَعلمات طريقة معاودة الاتصال السمةView
التي يختارها المستخدم وعنصرContextMenu.ContextMenuInfo
الذي يقدّم معلومات إضافية عن العنصر الذي تم اختياره. وإذا كان لنشاطك عدة ملفات شخصية يوفّر كل منها قائمة سياق مختلفة، يمكنك استخدام هذه المَعلمات لتحديد قائمة السياقات التي يجب تضخيمها. نفِّذ السمة
onContextItemSelected()
، كما هو موضّح في المثال التالي. عندما يختار المستخدم عنصرًا في القائمة، يستدعي النظام هذه الطريقة لتتمكّن من تنفيذ الإجراء المناسب.Kotlin
override fun onContextItemSelected(item: MenuItem): Boolean { val info = item.menuInfo as AdapterView.AdapterContextMenuInfo return when (item.itemId) { R.id.edit -> { editNote(info.id) true } R.id.delete -> { deleteNote(info.id) true } else -> super.onContextItemSelected(item) } }
Java
@Override public boolean onContextItemSelected(MenuItem item) { AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo(); switch (item.getItemId()) { case R.id.edit: editNote(info.id); return true; case R.id.delete: deleteNote(info.id); return true; default: return super.onContextItemSelected(item); } }
تطلب الطريقة
getItemId()
البحث عن رقم تعريف عنصر القائمة المحدّد، والذي تمنحه لكل عنصر في القائمة في ملف XML باستخدام السمةandroid:id
، كما هو موضّح في تحديد قائمة في XML.عندما تتم معالجة عنصر في القائمة بنجاح، يمكنك إرجاع
true
. إذا لم تتمكن من التعامل مع عنصر القائمة، مرِّر عنصر القائمة إلى التنفيذ المتميز. إذا كان نشاطك يتضمّن أجزاءً، يتلقّى النشاط معاودة الاتصال هذه أولاً. من خلال استدعاء الفئة الفائقة عند عدم معالجتها، يمرر النظام الحدث إلى طريقة معاودة الاتصال المناسبة في كل جزء، بالترتيب الذي تتم إضافة كل جزء به، حتى يتم عرضtrue
أوfalse
. وتؤدي عمليات التنفيذ التلقائية للسمتَينActivity
وandroid.app.Fragment
إلى عرض السمةfalse
، لذا يجب دائمًا طلب الفئة الفائقة عند عدم معالجتها.
استخدام وضع الإجراءات المستندة إلى السياق
"وضع الإجراء المستند إلى السياق" هو تطبيق من أنظمة تشغيل "ActionMode
" يركّز على تفاعل المستخدمين من أجل تنفيذ إجراءات سياقية. عندما يفعّل المستخدم هذا الوضع من خلال اختيار عنصر، يظهر
شريط إجراءات سياقية في أعلى الشاشة لعرض الإجراءات
التي يمكن للمستخدم تنفيذها على العناصر المحددة. عند تفعيل هذا الوضع، يمكن للمستخدم اختيار عدة عناصر، إذا كان تطبيقك يتيح ذلك، ويمكنه إلغاء اختيار العناصر والمتابعة للتنقّل ضمن النشاط. يكون وضع الإجراء غير مفعّل
ويختفي شريط الإجراءات المستندة إلى السياق عندما يلغي المستخدم اختيار كل العناصر
أو ينقر على زر "الرجوع" أو ينقر على الإجراء تمّ
على الجانب الأيمن من الشريط.
بالنسبة إلى طرق العرض التي توفر إجراءات متعلقة بالسياق، عليك عادةً استدعاء وضع الإجراء السياقي عند وقوع أحد هذين الحدثين أو كليهما:
- يضغط المستخدم مع الاستمرار على شاشة العرض.
- يحدّد المستخدم مربّع اختيار أو مكوّن واجهة مستخدم مشابهًا ضمن طريقة العرض.
تعتمد كيفية استدعاء تطبيقك لوضع الإجراء السياقي وتحديد سلوك كل إجراء على تصميمك. هناك تصميمان:
- تنطبق على الإجراءات السياقية بشأن وجهات النظر الفردية والعشبية.
- لتنفيذ الإجراءات السياقية دُفعة على مجموعات من العناصر في
RecyclerView
، ما يتيح للمستخدم اختيار عناصر متعددة وتنفيذ إجراء عليها جميعًا.
تصف الأقسام التالية الإعداد المطلوب لكل سيناريو.
تفعيل وضع الإجراءات المستندة إلى السياق في مشاهدات فردية
إذا كنت تريد استدعاء وضع الإجراء المستند إلى السياق فقط عندما يحدّد المستخدم طرق عرض معيّنة، يجب تنفيذ ما يلي:
- نفِّذ واجهة
ActionMode.Callback
كما هو موضّح في المثال التالي. في طرق معاودة الاتصال الخاصة به، يمكنك تحديد الإجراءات لشريط الإجراءات السياقي، والاستجابة لأحداث النقر على بنود العمل، والتعامل مع أحداث مراحل النشاط الأخرى لوضع الإجراء.Kotlin
private val actionModeCallback = object : ActionMode.Callback { // Called when the action mode is created. startActionMode() is called. override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean { // Inflate a menu resource providing context menu items. val inflater: MenuInflater = mode.menuInflater inflater.inflate(R.menu.context_menu, menu) return true } // Called each time the action mode is shown. Always called after // onCreateActionMode, and might be called multiple times if the mode // is invalidated. override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean { return false // Return false if nothing is done } // Called when the user selects a contextual menu item. override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean { return when (item.itemId) { R.id.menu_share -> { shareCurrentItem() mode.finish() // Action picked, so close the CAB. true } else -> false } } // Called when the user exits the action mode. override fun onDestroyActionMode(mode: ActionMode) { actionMode = null } }
Java
private ActionMode.Callback actionModeCallback = new ActionMode.Callback() { // Called when the action mode is created. startActionMode() is called. @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { // Inflate a menu resource providing context menu items. MenuInflater inflater = mode.getMenuInflater(); inflater.inflate(R.menu.context_menu, menu); return true; } // Called each time the action mode is shown. Always called after // onCreateActionMode, and might be called multiple times if the mode // is invalidated. @Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) { return false; // Return false if nothing is done. } // Called when the user selects a contextual menu item. @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { switch (item.getItemId()) { case R.id.menu_share: shareCurrentItem(); mode.finish(); // Action picked, so close the CAB. return true; default: return false; } } // Called when the user exits the action mode. @Override public void onDestroyActionMode(ActionMode mode) { actionMode = null; } };
تتشابه عمليات استدعاء الأحداث هذه تقريبًا مع استدعاءات قائمة الخيارات، باستثناء أنّ كل من هذه يمرّر أيضًا الكائن
ActionMode
المرتبط بالحدث. يمكنك استخدام واجهات برمجة تطبيقاتActionMode
لإجراء تغييرات مختلفة على CAB، مثل مراجعة العنوان والعنوان الفرعي باستخدامsetTitle()
وsetSubtitle()
، وذلك للإشارة إلى عدد العناصر التي تم اختيارها.تضبط العيّنة السابقة المتغيّر
actionMode
علىnull
عند إتلاف وضع الإجراء. في الخطوة التالية، اطّلِع على طريقة إعداده ومدى فائدة حفظ المتغيّر العضو في نشاطك أو الجزء. - يمكنك طلب
startActionMode()
عندما تريد عرض الشريط، مثلاً عندما يلمس المستخدم لمسة مع الاستمرار على شاشة العرض.Kotlin
someView.setOnLongClickListener { view -> // Called when the user performs a touch & hold on someView. when (actionMode) { null -> { // Start the CAB using the ActionMode.Callback defined earlier. actionMode = activity?.startActionMode(actionModeCallback) view.isSelected = true true } else -> false } }
Java
someView.setOnLongClickListener(new View.OnLongClickListener() { // Called when the user performs a touch & hold on someView. public boolean onLongClick(View view) { if (actionMode != null) { return false; } // Start the CAB using the ActionMode.Callback defined earlier. actionMode = getActivity().startActionMode(actionModeCallback); view.setSelected(true); return true; } });
عند استدعاء الدالة
startActionMode()
، يعرض النظامActionMode
الذي تم إنشاؤه. ومن خلال حفظ هذه السمة في متغيّر عضو، يمكنك إجراء تغييرات على شريط الإجراءات المستند إلى السياق استجابةً لأحداث أخرى. في العيّنة السابقة، يتم استخدامActionMode
لضمان عدم إعادة إنشاء المثيلActionMode
إذا كان نشطًا، وذلك من خلال التحقق مما إذا كان العضو فارغًا قبل بدء وضع الإجراء.
إنشاء قائمة منبثقة
![صورة تعرض قائمة منبثقة في تطبيق Gmail، تظهر في أعلى يسار الشاشة بزر القائمة الكاملة.](https://developer.android.com/static/images/ui/popupmenu.png?authuser=3&hl=ar)
PopupMenu
هي قائمة مشروطة مثبَّتة في View
. ويظهر أسفل طريقة عرض الإرساء
إذا كان هناك مساحة، أو أعلى العرض. وهذا مفيد لما يلي:
- توفير قائمة نمط كامل للإجراءات التي تتعلق بمحتوى محدد، مثل عناوين البريد الإلكتروني في Gmail، كما هو موضح في الشكل 4.
- توفير جزء ثانٍ من جملة أوامر، مثل زر يحمل علامة إضافة يؤدي إلى ظهور قائمة منبثقة بخيارات إضافة مختلفة.
- يتم توفير قائمة مشابهة لـ
Spinner
لا تحتفظ باختيار دائم.
إذا حددت قائمتك بتنسيق XML، إليك كيفية إظهار القائمة المنبثقة:
- يمكنك إنشاء مثيل
PopupMenu
باستخدام الدالة الإنشائية الخاصة به، والتي ستنقل التطبيق الحاليContext
والسمةView
التي ترتبط بها القائمة. - استخدِم
MenuInflater
لتكبير مورد القائمة إلى الكائنMenu
الذي يعرضهPopupMenu.getMenu()
. - الاتصال بالرقم
PopupMenu.show()
.
على سبيل المثال، إليك زر يعرض قائمة منبثقة:
<ImageButton android:id="@+id/dropdown_menu" android:layout_width="wrap_content" android:layout_height="wrap_content" android:contentDescription="@string/descr_overflow_button" android:src="@drawable/arrow_drop_down" />
يمكن للنشاط بعد ذلك إظهار القائمة المنبثقة مثل هذه:
Kotlin
findViewById<ImageButton>(R.id.dropdown_menu).setOnClickListener { val popup = PopupMenu(this, it) val inflater: MenuInflater = popup.menuInflater inflater.inflate(R.menu.actions, popup.menu) popup.show() }
Java
findViewById(R.id.dropdown_menu).setOnClickListener(v -> { PopupMenu popup = new PopupMenu(this, v); popup.getMenuInflater().inflate(R.menu.actions, popup.getMenu()); popup.show(); });
يتم إغلاق القائمة عندما يحدّد المستخدم عنصرًا أو ينقر خارج منطقة القائمة. يمكنك الاستماع إلى حدث إغلاق باستخدام "PopupMenu.OnDismissListener
".
التعامل مع الأحداث الناتجة عن النقر
لتنفيذ إجراء عندما يختار المستخدم عنصرًا في القائمة، عليك تنفيذ
واجهة PopupMenu.OnMenuItemClickListener
وتسجيلها في PopupMenu
من خلال استدعاء
setOnMenuItemclickListener()
.
عندما يختار المستخدم عنصرًا، يستدعي النظام
onMenuItemClick()
معاودة الاتصال في واجهتك.
يظهر ذلك في المثال التالي:
Kotlin
fun showMenu(v: View) { PopupMenu(this, v).apply { // MainActivity implements OnMenuItemClickListener. setOnMenuItemClickListener(this@MainActivity) inflate(R.menu.actions) show() } } override fun onMenuItemClick(item: MenuItem): Boolean { return when (item.itemId) { R.id.archive -> { archive(item) true } R.id.delete -> { delete(item) true } else -> false } }
Java
public void showMenu(View v) { PopupMenu popup = new PopupMenu(this, v); // This activity implements OnMenuItemClickListener. popup.setOnMenuItemClickListener(this); popup.inflate(R.menu.actions); popup.show(); } @Override public boolean onMenuItemClick(MenuItem item) { switch (item.getItemId()) { case R.id.archive: archive(item); return true; case R.id.delete: delete(item); return true; default: return false; } }
إنشاء مجموعة قوائم طعام
مجموعة القوائم هي مجموعة من عناصر القائمة التي تشترك في سمات معينة. باستخدام المجموعة، يمكنك تنفيذ ما يلي:
- يمكنك إظهار جميع العناصر أو إخفاؤها باستخدام
setGroupVisible()
. - تفعيل أو إيقاف كل العناصر باستخدام
setGroupEnabled()
- حدِّد ما إذا كان يمكن التحقّق من جميع العناصر باستخدام
setGroupCheckable()
.
يمكنك إنشاء مجموعة من خلال دمج عناصر <item>
داخل عنصر <group>
في مورد القائمة أو من خلال تحديد رقم تعريف مجموعة باستخدام الطريقة add()
.
في ما يلي مثال لمورد قائمة يتضمن مجموعة:
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/menu_save" android:icon="@drawable/menu_save" android:title="@string/menu_save" /> <!-- menu group --> <group android:id="@+id/group_delete"> <item android:id="@+id/menu_archive" android:title="@string/menu_archive" /> <item android:id="@+id/menu_delete" android:title="@string/menu_delete" /> </group> </menu>
تظهر العناصر الموجودة في المجموعة على نفس مستوى العنصر الأول - جميع العناصر الثلاثة في القائمة هي أشقاء. ومع ذلك، يمكنك تعديل سمات العنصرين في المجموعة من خلال الإشارة إلى معرّف المجموعة واستخدام الطرق السابقة. ولا يفصل النظام مطلقًا العناصر المجمّعة. على سبيل المثال، إذا أعلنت عن android:showAsAction="ifRoom"
لكل عنصر، سيظهر كلاهما في شريط الإجراءات أو سيظهر كلاهما في المجموعة الكاملة للإجراءات.
استخدام عناصر القائمة القابلة للتحديد
يمكن أن تكون القائمة مفيدة كواجهة لتفعيل الخيارات وإيقافها، أو باستخدام مربع اختيار للخيارات المستقلة، أو أزرار اختيار لمجموعات من الخيارات المتنافية. يعرض الشكل 5 قائمة فرعية تحتوي على عناصر يمكن التحقق منها باستخدام أزرار الاختيار.
يمكنك تحديد السلوك القابل للالتحقّق لعناصر القائمة الفردية باستخدام السمة android:checkable
في العنصر <item>
أو لمجموعة بأكملها باستخدام السمة android:checkableBehavior
في العنصر <group>
. على سبيل المثال، يمكن التحقق من جميع العناصر
في مجموعة القوائم هذه باستخدام زر اختيار:
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <group android:checkableBehavior="single"> <item android:id="@+id/red" android:title="@string/red" /> <item android:id="@+id/blue" android:title="@string/blue" /> </group> </menu>
تقبل السمة android:checkableBehavior
أيًا مما يلي:
single
- يمكن التحقّق من عنصر واحد فقط من المجموعة، ما يؤدي إلى ظهور أزرار الاختيار.
all
- يمكن التحقّق من كل العناصر، ما يؤدي إلى ظهور مربّعات اختيار.
none
- لا يمكن تحديد أي عناصر.
يمكنك تطبيق حالة محددة تلقائيًا على عنصر باستخدام
السمة android:checked
في العنصر <item>
،
وتغييرها في الرمز باستخدام الطريقة
setChecked()
.
عند تحديد عنصر قابل للتحديد، يستدعي النظام طريقة معاودة الاتصال
المحدّدة للعنصر، مثل onOptionsItemSelected()
.
هذا هو المكان الذي يتم فيه ضبط حالة مربّع الاختيار، لأن مربّع الاختيار أو زر الاختيار لا يغيّر حالته تلقائيًا. يمكنك الاستعلام عن الحالة الحالية للعنصر، كما كانت قبل أن يختاره المستخدم، باستخدام
isChecked()
ثم ضبط الحالة التي تم اختيارها باستخدام setChecked()
. يظهر ذلك في المثال التالي:
Kotlin
override fun onOptionsItemSelected(item: MenuItem): Boolean { return when (item.itemId) { R.id.vibrate, R.id.dont_vibrate -> { item.isChecked = !item.isChecked true } else -> super.onOptionsItemSelected(item) } }
Java
@Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.vibrate: case R.id.dont_vibrate: if (item.isChecked()) item.setChecked(false); else item.setChecked(true); return true; default: return super.onOptionsItemSelected(item); } }
إذا لم يتم ضبط الحالة المحددة بهذه الطريقة، لن تتغير الحالة المرئية لمربّع الاختيار أو زر الاختيار عندما يحدّده المستخدم. عندما تقوم بتعيين الحالة، يحافظ النشاط على الحالة المحددة للعنصر بحيث عندما يفتح المستخدم القائمة لاحقًا، تكون الحالة المحددة التي حددتها مرئية.
إضافة أصناف في القائمة استنادًا إلى هدف
قد تريد أحيانًا أن يبدأ عنصر في القائمة نشاطًا باستخدام Intent
،
سواء كان نشاطًا في تطبيقك أو تطبيقًا آخر. وعندما تدرك الغرض الذي تريد استخدامه وكان لديك عنصر قائمة محدد لبدء الغرض، يمكنك تنفيذ الغرض باستخدام startActivity()
أثناء طريقة معاودة الاتصال المناسبة التي اخترتها للمحتوى، مثل
عملية معاودة الاتصال onOptionsItemSelected()
.
ومع ذلك، إذا لم تكن متأكدًا من أن جهاز المستخدم يحتوي على تطبيق يعالج الغرض، فإن إضافة عنصر قائمة يستدعي ذلك يمكن أن يؤدي إلى عنصر قائمة لا يعمل، لأن القصد قد لا يتحول إلى نشاط. لحلّ هذه المشكلة، يتيح لك Android إضافة عناصر القائمة ديناميكيًا إلى قائمتك عندما يعثر على الأنشطة التي تحقّق هدفك على الجهاز.
لإضافة عناصر في القائمة بناءً على الأنشطة المتاحة التي تقبل النية، اتّبِع الخطوات التالية:
- حدِّد هدفًا من خلال الفئة
CATEGORY_ALTERNATIVE
أوCATEGORY_SELECTED_ALTERNATIVE
أو كلتيهما، بالإضافة إلى أي متطلبات أخرى. - الاتصال بـ
Menu.addIntentOptions()
يبحث Android بعد ذلك عن أي تطبيقات يمكنها تنفيذ إجراء intent ويضيفها إلى قائمتك.
فإذا لم تكن هناك أي تطبيقات مثبتة تفي بالغرض، فلن تتم إضافة عناصر قائمة.
يظهر ذلك في المثال التالي:
Kotlin
override fun onCreateOptionsMenu(menu: Menu): Boolean { super.onCreateOptionsMenu(menu) // Create an Intent that describes the requirements to fulfill, to be // included in the menu. The offering app must include a category value // of Intent.CATEGORY_ALTERNATIVE. val intent = Intent(null, dataUri).apply { addCategory(Intent.CATEGORY_ALTERNATIVE) } // Search and populate the menu with acceptable offering apps. menu.addIntentOptions( R.id.intent_group, // Menu group to which new items are added. 0, // Unique item ID (none). 0, // Order for the items (none). this.componentName, // The current activity name. null, // Specific items to place first (none). intent, // Intent created above that describes the requirements. 0, // Additional flags to control items (none). null) // Array of MenuItems that correlate to specific items (none). return true }
Java
@Override public boolean onCreateOptionsMenu(Menu menu){ super.onCreateOptionsMenu(menu); // Create an Intent that describes the requirements to fulfill, to be // included in the menu. The offering app must include a category value // of Intent.CATEGORY_ALTERNATIVE. Intent intent = new Intent(null, dataUri); intent.addCategory(Intent.CATEGORY_ALTERNATIVE); // Search and populate the menu with acceptable offering apps. menu.addIntentOptions( R.id.intent_group, // Menu group to which new items are added. 0, // Unique item ID (none). 0, // Order for the items (none). this.getComponentName(), // The current activity name. null, // Specific items to place first (none). intent, // Intent created above that describes the requirements. 0, // Additional flags to control items (none). null); // Array of MenuItems that correlate to specific items (none). return true; }
ولكل نشاط يتمّ العثور عليه يوفّر فلتر أهداف يتطابق مع الهدف المحدّد، تتمّ إضافة عنصر قائمة باستخدام القيمة في android:label
لفلتر الأهداف كعنوان عنصر القائمة ورمز التطبيق كرمز عنصر القائمة. تُرجع الطريقة addIntentOptions()
عدد عناصر
القائمة التي تمت إضافتها.
السماح بإضافة نشاطك إلى قوائم أخرى
يمكنك تقديم خدمات نشاطك إلى تطبيقات أخرى كي يتم إدراج تطبيقك في قائمة التطبيقات الأخرى، مع عكس الأدوار الموضّحة سابقًا.
لتضمينها في قوائم التطبيقات الأخرى، حدِّد فلتر أهداف كالمعتاد، ولكن أدرِج القيم CATEGORY_ALTERNATIVE
أو CATEGORY_SELECTED_ALTERNATIVE
أو كليهما لفئة فلتر الأهداف. يظهر ذلك في المثال التالي:
<intent-filter label="@string/resize_image"> ... <category android:name="android.intent.category.ALTERNATIVE" /> <category android:name="android.intent.category.SELECTED_ALTERNATIVE" /> ... </intent-filter>
اقرأ المزيد حول كتابة فلاتر الأهداف في فلاتر الأهداف والغايات.