القوائم هي أحد عناصر واجهة المستخدم الشائعة في العديد من أنواع التطبيقات. لتقديم تجربة مستخدم مألوفة ومتسقة، استخدِم واجهات برمجة التطبيقات 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>
لاستخدام القائمة في نشاطك، عليك _توسيع_ مورد القائمة، أي تحويل مورد XML إلى عنصر قابل للبرمجة باستخدام MenuInflater.inflate().
توضّح الأقسام التالية كيفية إنشاء قائمة لكل نوع من أنواع القوائم.
إنشاء قائمة خيارات
قائمة الخيارات، مثل تلك المعروضة في الشكل 1، هي المكان الذي يمكنك فيه تضمين الإجراءات والخيارات الأخرى ذات الصلة بسياق النشاط الحالي، مثل "بحث" و"إنشاء رسالة إلكترونية" و "الإعدادات".
يمكنك تعريف عناصر لقائمة الخيارات من الفئة الفرعية 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(). يعرض التنفيذ التلقائي القيمة false.
إذا كان نشاطك يتضمّن أجزاءً، يستدعي النظام أولاً onOptionsItemSelected() للنشاط، ثم لكل جزء بالترتيب الذي تمت إضافة الأجزاء به، إلى أن يعرض أحدها true أو يتم استدعاء جميع الأجزاء.
تغيير عناصر القائمة في وقت التشغيل
بعد أن يستدعي النظام onCreateOptionsMenu()، يحتفظ بنسخة من Menu التي تملأها ولا يستدعي onCreateOptionsMenu() مرة أخرى إلا إذا تم إبطال القائمة.
ومع ذلك، استخدِم onCreateOptionsMenu() لإنشاء حالة القائمة الأولية فقط وليس لإجراء تغييرات أثناء مراحل نشاط التطبيق.
إذا أردت تعديل قائمة الخيارات استنادًا إلى الأحداث التي تحدث أثناء دورة حياة النشاط، يمكنك إجراء ذلك في الطريقة onPrepareOptionsMenu(). تمنحك هذه الطريقة العنصر Menu كما هو حاليًا
لتتمكّن من تعديله، مثلاً عن طريق إضافة عناصر أو إزالتها أو إيقافها.
توفّر الأجزاء أيضًا
onPrepareOptionsMenu()
دالة ردّ الاتصال.
تُعتبر قائمة الخيارات مفتوحة دائمًا عندما يتم عرض عناصر القائمة في شريط التطبيق. عند وقوع حدث وتريد إجراء تعديل على القائمة، استدعِ الدالة
invalidateOptionsMenu()
لطلب أن يستدعي النظام الدالة onPrepareOptionsMenu().
إنشاء قائمة سياقية
تقدّم قائمة السياق إجراءات تؤثّر في عنصر أو إطار سياق معيّن في واجهة المستخدم. يمكنك توفير قائمة سياقية لأي طريقة عرض، ولكن يتم استخدامها في أغلب الأحيان مع العناصر في 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لإجراء تغييرات مختلفة على شريط التطبيق المخصص، مثل تعديل العنوان والعنوان الفرعي باستخدام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إذا كان نشطًا، وذلك من خلال التحقّق مما إذا كان العنصر قيمة فارغة قبل بدء وضع الإجراء.
إنشاء قائمة منبثقة
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،
سواء كان نشاطًا في تطبيقك أو تطبيقًا آخر. عندما
تعرف الـ intent الذي تريد استخدامه ولديك عنصر قائمة محدّد يبدأ
الـ intent، يمكنك تنفيذ الـ intent باستخدام
startActivity()
أثناء طريقة رد الاتصال المناسبة on-item-selected، مثل
طريقة رد الاتصال onOptionsItemSelected().
ومع ذلك، إذا لم تكن متأكدًا من أنّ جهاز المستخدم يتضمّن تطبيقًا يمكنه معالجة الغرض، قد تؤدي إضافة عنصر قائمة يستدعيه إلى ظهور عنصر قائمة لا يعمل، لأنّه قد لا يتم تحويل الغرض إلى نشاط. لحلّ هذه المشكلة، يتيح لك نظام التشغيل Android إضافة عناصر قائمة بشكل ديناميكي إلى قائمتك عندما يعثر على أنشطة على الجهاز يمكنها التعامل مع هدفك.
لإضافة عناصر قائمة استنادًا إلى الأنشطة المتاحة التي تقبل غرضًا، اتّبِع الخطوات التالية:
- حدِّد نية باستخدام الفئة
CATEGORY_ALTERNATIVEأوCATEGORY_SELECTED_ALTERNATIVEأو كلتيهما، بالإضافة إلى أي متطلبات أخرى. - الاتصال على
Menu.addIntentOptions()يبحث Android بعد ذلك عن أي تطبيقات يمكنها تنفيذ الغرض ويضيفها إلى القائمة.
إذا لم تكن هناك تطبيقات مثبَّتة تستوفي الغرض، لن تتم إضافة أي عناصر إلى القائمة.
يظهر ذلك في المثال التالي:
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; }
لكل نشاط تم العثور عليه يوفّر intent filter مطابقًا للـ intent المحدّد، تتم إضافة عنصر في القائمة باستخدام القيمة في android:label للـ intent filter كعنوان لعنصر في القائمة ورمز التطبيق كرمز لعنصر في القائمة. تعرض الطريقة addIntentOptions() عدد عناصر القائمة التي تمت إضافتها.
السماح بإضافة نشاطك إلى قوائم أخرى
يمكنك تقديم خدمات نشاطك إلى تطبيقات أخرى حتى يمكن تضمين تطبيقك في قائمة التطبيقات الأخرى، ما يؤدي إلى عكس الأدوار الموضّحة سابقًا.
لتضمين تطبيقك في قوائم التطبيقات الأخرى، عليك تحديد intent filter كالمعتاد، ولكن مع تضمين القيم CATEGORY_ALTERNATIVE أو CATEGORY_SELECTED_ALTERNATIVE أو كليهما لفئة intent filter. يظهر ذلك في المثال التالي:
<intent-filter label="@string/resize_image"> ... <category android:name="android.intent.category.ALTERNATIVE" /> <category android:name="android.intent.category.SELECTED_ALTERNATIVE" /> ... </intent-filter>
يمكنك الاطّلاع على مزيد من المعلومات حول كتابة فلاتر الأهداف في مقالة الأهداف وفلاتر الأهداف.