اضافه کردن منوها

روش Compose را امتحان کنید
Jetpack Compose جعبه ابزار UI توصیه شده برای اندروید است. با نحوه افزودن کامپوننت در Compose آشنا شوید.

منوها جزء رابط کاربری رایج در بسیاری از انواع برنامه ها هستند. برای ارائه یک تجربه کاربری آشنا و ثابت، از API های Menu برای ارائه اقدامات کاربر و سایر گزینه ها در فعالیت های خود استفاده کنید.

تصویری که نمونه ای از منوی سرریز را نشان می دهد
شکل 1. منویی که با ضربه زدن به نماد فعال می شود و در زیر نماد منوی سرریز ظاهر می شود.

این سند نحوه ایجاد سه نوع اصلی منو یا ارائه عملکرد را در تمام نسخه‌های اندروید نشان می‌دهد:

منوی گزینه ها و نوار برنامه
منوی گزینه ها مجموعه اصلی از آیتم های منو برای یک فعالیت است. این جایی است که اقداماتی را که تأثیر کلی بر برنامه دارند، مانند «جستجو»، «نوشتن ایمیل» و «تنظیمات» قرار می‌دهید.

بخش Create an option menu را ببینید.

منوی زمینه و حالت عمل متنی
منوی زمینه یک منوی شناور است که وقتی کاربر یک عنصر را لمس و نگه می‌دارد ظاهر می‌شود. اقداماتی را ارائه می دهد که بر محتوا یا چارچوب زمینه انتخاب شده تأثیر می گذارد.

حالت کنش متنی موارد اقدامی را که بر محتوای انتخابی تأثیر می‌گذارند در نواری در بالای صفحه نمایش می‌دهد و به کاربر امکان می‌دهد چندین مورد را انتخاب کند.

بخش ایجاد منوی متنی را ببینید.

منوی پاپ آپ
یک منوی بازشو لیستی عمودی از مواردی را نشان می‌دهد که به نمایی که منو را فراخوانی می‌کند متصل شده‌اند. برای ارائه سرریز اقدامات مربوط به محتوای خاص یا ارائه گزینه هایی برای قسمت دوم یک فرمان خوب است. کنش‌های موجود در منوی بازشو مستقیماً بر محتوای مربوطه تأثیر نمی‌گذارند - این همان چیزی است که اقدامات زمینه‌ای انجام می‌شود. در عوض، منوی بازشو برای اقدامات گسترده ای است که به مناطق محتوای فعالیت شما مربوط می شود.

بخش Create a popup menu را ببینید.

یک منو در XML تعریف کنید

برای همه انواع منو، اندروید یک قالب استاندارد XML برای تعریف آیتم های منو ارائه می کند. به جای ایجاد یک منو در کد فعالیت خود، یک منو و همه موارد آن را در یک منبع منوی XML تعریف کنید. سپس می توانید منبع منو را در اکتیویتی یا قطعه خود اضافه کنید - آن را به عنوان یک شی Menu بارگیری کنید.

استفاده از یک منبع منو به دلایل زیر تمرین خوبی است:

  • تجسم ساختار منو در XML آسانتر است.
  • محتوای منو را از کد رفتاری برنامه شما جدا می کند.
  • این به شما امکان می‌دهد با استفاده از چارچوب منابع برنامه، تنظیمات منوی جایگزین را برای نسخه‌های پلتفرم مختلف، اندازه‌های صفحه و سایر تنظیمات ایجاد کنید.

برای تعریف یک منو، یک فایل XML در دایرکتوری res/menu/ پروژه خود ایجاد کنید و منو را با عناصر زیر بسازید:

<menu>
یک Menu تعریف می کند که محفظه ای برای آیتم های منو است. عنصر <menu> باید گره ریشه فایل باشد و می تواند یک یا چند عنصر <item> و <group> را در خود جای دهد.
<item>
یک MenuItem ایجاد می کند که نشان دهنده یک آیتم در یک منو است. این عنصر می تواند حاوی یک عنصر <menu> تودرتو برای ایجاد یک زیر منو باشد.
<group>
یک ظرف اختیاری و نامرئی برای عناصر <item> . این به شما امکان می‌دهد آیتم‌های منو را دسته‌بندی کنید تا ویژگی‌هایی مانند حالت فعال و قابلیت مشاهده را به اشتراک بگذارند. برای اطلاعات بیشتر، بخش Create a menu group را ببینید.

در اینجا یک منوی نمونه با نام 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_ کنید و با استفاده از MenuInflater.inflate() منبع XML را به یک شی قابل برنامه ریزی تبدیل کنید. بخش‌های زیر نحوه ایجاد یک منو برای هر نوع منو را نشان می‌دهد.

یک منوی گزینه ها ایجاد کنید

منوی گزینه ها، مانند آنچه در شکل 1 نشان داده شده است، جایی است که شما اقدامات و سایر گزینه های مرتبط با زمینه فعالیت فعلی را شامل می شود، مانند "جستجو"، "نوشتن ایمیل" و "تنظیمات".

تصویری که نوار برنامه را برای برنامه Google Sheets نشان می‌دهد
شکل 2. برنامه Google Sheets، چندین دکمه از جمله دکمه سرریز عمل را نشان می دهد.

می‌توانید موارد را برای منوی گزینه‌ها از زیر کلاس Activity یا زیر کلاس Fragment اعلام کنید. اگر هم فعالیت شما و هم قطعات شما موارد را برای منوی گزینه ها اعلام می کنند، موارد در رابط کاربری ترکیب می شوند. آیتم های اکتیویتی ابتدا ظاهر می شوند و پس از آن موارد هر قطعه به ترتیبی که قطعات به فعالیت اضافه می شوند ظاهر می شوند. در صورت لزوم، می‌توانید آیتم‌های منو را با ویژگی android:orderInCategory در هر <item> که باید جابجا کنید، مرتب کنید.

برای تعیین منوی گزینه‌ها برای یک فعالیت، onCreateOptionsMenu() را لغو کنید. Fragment ها پاسخ تماس onCreateOptionsMenu() خود را ارائه می کنند. در این روش، می‌توانید منبع منوی خود را که در XML تعریف شده است ، در Menu ارائه شده در پاسخ به تماس اضافه کنید. این در مثال زیر نشان داده شده است:

کاتلین

override fun onCreateOptionsMenu(menu: Menu): Boolean {
    val inflater: MenuInflater = menuInflater
    inflater.inflate(R.menu.game_menu, menu)
    return true
}

جاوا

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.game_menu, menu);
    return true;
}

همچنین می توانید آیتم های منو را با استفاده از add() اضافه کنید و آیتم ها را با findItem() بازیابی کنید تا ویژگی های آنها را با MenuItem API ها اصلاح کنید.

رویدادهای کلیک را مدیریت کنید

هنگامی که کاربر موردی را از منوی گزینه‌ها انتخاب می‌کند، از جمله موارد اقدام در نوار برنامه، سیستم متد onOptionsItemSelected() فعالیت شما را فراخوانی می‌کند. این متد MenuItem انتخاب شده را ارسال می کند. می‌توانید با فراخوانی getItemId() مورد را شناسایی کنید، که شناسه منحصربه‌فرد برای آیتم منو را باز می‌گرداند که توسط ویژگی android:id در منبع منو یا با یک عدد صحیح داده‌شده به متد add() تعریف شده است. می توانید این شناسه را با آیتم های منوی شناخته شده مطابقت دهید تا عمل مناسب را انجام دهید.

کاتلین

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)
    }
}

جاوا

@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 برگردانید. اگر آیتم منو را مدیریت نمی‌کنید، اجرای superclass onOptionsItemSelected() را فراخوانی کنید. اجرای پیش فرض false را برمی گرداند.

اگر اکتیویتی شما شامل قطعات باشد، سیستم ابتدا onOptionsItemSelected() را برای اکتیویتی فراخوانی می کند، سپس برای هر قطعه به ترتیب فرگمنت ها اضافه می شوند، تا زمانی که یکی true را برگرداند یا همه فرگمنت ها فراخوانی شوند.

تغییر آیتم های منو در زمان اجرا

بعد از اینکه سیستم onCreateOptionsMenu() را فراخوانی کرد، نمونه‌ای از Menu را که پر کرده‌اید حفظ می‌کند و دیگر onCreateOptionsMenu() فراخوانی نمی‌کند مگر اینکه منو باطل شود. با این حال، از onCreateOptionsMenu() فقط برای ایجاد حالت منوی اولیه و عدم ایجاد تغییرات در طول چرخه فعالیت استفاده کنید.

اگر می‌خواهید منوی گزینه‌ها را بر اساس رویدادهایی که در طول چرخه حیات فعالیت رخ می‌دهند تغییر دهید، می‌توانید این کار را در متد onPrepareOptionsMenu() انجام دهید. این روش شی Menu را همانطور که در حال حاضر وجود دارد به شما می دهد تا بتوانید آن را تغییر دهید، مانند افزودن، حذف یا غیرفعال کردن موارد. Fragment ها همچنین یک پاسخ تماس onPrepareOptionsMenu() را ارائه می دهند.

وقتی آیتم های منو در نوار برنامه ارائه می شوند، منوی گزینه ها همیشه باز در نظر گرفته می شود. هنگامی که یک رویداد رخ می دهد و می خواهید یک به روز رسانی منو انجام دهید، invalidateOptionsMenu() را فراخوانی کنید تا درخواست کنید که سیستم onPrepareOptionsMenu() را فراخوانی کند.

یک منوی متنی ایجاد کنید

تصویری که منوی زمینه شناور را نشان می دهد
شکل 3. منوی زمینه شناور.

یک منوی متنی اقداماتی را ارائه می دهد که بر یک مورد خاص یا چارچوب زمینه در رابط کاربری تأثیر می گذارد. شما می توانید یک منوی زمینه برای هر نما تهیه کنید، اما آنها اغلب برای موارد موجود در RecylerView یا سایر مجموعه های نمایش استفاده می شوند که در آن کاربر می تواند اقدامات مستقیم را روی هر مورد انجام دهد.

دو راه برای ارائه کنش‌های متنی وجود دارد:

  • در یک منوی زمینه شناور . یک منو به عنوان یک لیست شناور از آیتم های منو ظاهر می شود، شبیه به یک گفتگو، زمانی که کاربر یک نما را لمس و نگه می دارد که از منوی زمینه پشتیبانی می کند. کاربران می توانند یک عمل متنی را روی یک مورد در یک زمان انجام دهند.
  • در حالت کنش متنی . این حالت یک پیاده‌سازی سیستمی از ActionMode است که یک نوار کنش متنی یا CAB را در بالای صفحه با آیتم‌های اقدامی نشان می‌دهد که بر آیتم(های) انتخاب شده تأثیر می‌گذارد. هنگامی که این حالت فعال است، اگر برنامه شما از آن پشتیبانی کند، کاربران می‌توانند همزمان روی چندین مورد عمل کنند.

توجه: منوی زمینه از میانبرهای مورد و نمادهای مورد پشتیبانی نمی کند.

یک منوی زمینه شناور ایجاد کنید

برای ارائه یک منوی زمینه شناور، موارد زیر را انجام دهید:

  1. با فراخوانی registerForContextMenu() و ارسال View به آن، فهرستی را که View the context menu مرتبط است، ثبت کنید.

    اگر فعالیت شما از RecyclerView استفاده می‌کند و می‌خواهید هر آیتم همان منوی زمینه را ارائه دهد، با ارسال RecyclerView به registerForContextMenu() همه موارد را برای یک منوی زمینه ثبت کنید.

  2. متد onCreateContextMenu() را در Activity یا Fragment خود پیاده کنید.

    هنگامی که نمای ثبت شده یک رویداد لمسی و نگهداری را دریافت می کند، سیستم متد onCreateContextMenu() شما را فراخوانی می کند. اینجاست که شما آیتم های منو را تعریف می کنید، معمولاً با افزایش یک منبع منو، مانند مثال زیر:

    کاتلین

        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)
        }
        

    جاوا

        @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 که اطلاعات بیشتری در مورد مورد انتخاب شده ارائه می دهد. اگر فعالیت شما دارای چندین نما است که هر کدام منوی زمینه متفاوتی را ارائه می دهند، ممکن است از این پارامترها برای تعیین اینکه کدام منوی زمینه را باید افزایش دهید استفاده کنید.

  3. همانطور که در مثال زیر نشان داده شده است، onContextItemSelected() را پیاده سازی کنید. هنگامی که کاربر یک آیتم منو را انتخاب می کند، سیستم این روش را فراخوانی می کند تا بتوانید اقدام مناسب را انجام دهید.

    کاتلین

        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)
            }
        }
        

    جاوا

        @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() شناسه آیتم منوی انتخاب شده را جستجو می کند، که شما با استفاده از ویژگی android:id به هر آیتم منو در XML اختصاص می دهید، همانطور که در تعریف منو در XML نشان داده شده است.

    وقتی با موفقیت یک آیتم منو را مدیریت کردید، true برگردانید. اگر آیتم منو را مدیریت نمی کنید، آیتم منو را به اجرای سوپرکلاس منتقل کنید. اگر فعالیت شما شامل قطعات باشد، فعالیت ابتدا این تماس را دریافت می کند. با فراخوانی سوپرکلاس در صورت کنترل نشدن، سیستم رویداد را به متد مربوط به فراخوانی در هر قطعه، یکی یکی به ترتیب اضافه شدن هر قطعه، تا زمانی که true یا false برگردانده شود، ارسال می کند. پیاده‌سازی‌های پیش‌فرض Activity و android.app.Fragment false را برمی‌گردانند، بنابراین همیشه زمانی که کنترل نمی‌شود، سوپرکلاس را فراخوانی کنید.

از حالت کنش متنی استفاده کنید

حالت کنش متنی یک پیاده سازی سیستمی از ActionMode است که تعامل کاربر را بر روی انجام اقدامات متنی متمرکز می کند. هنگامی که کاربر با انتخاب یک مورد، این حالت را فعال می‌کند، یک نوار کنش متنی در بالای صفحه ظاهر می‌شود تا اقداماتی را که کاربر می‌تواند روی آیتم‌های انتخاب‌شده انجام دهد، نمایش می‌دهد. وقتی این حالت فعال است، اگر برنامه شما از آن پشتیبانی می‌کند، کاربر می‌تواند چندین مورد را انتخاب کند و می‌تواند موارد را لغو انتخاب کند و به پیمایش در فعالیت ادامه دهد. حالت کنش غیرفعال می‌شود و وقتی کاربر همه موارد را از حالت انتخاب خارج می‌کند، روی دکمه برگشت ضربه می‌زند یا روی عملکرد انجام شده در سمت چپ نوار ضربه می‌زند، نوار کنش متنی ناپدید می‌شود.

برای نماهایی که کنش‌های متنی را ارائه می‌کنند، معمولاً زمانی که یکی از این دو رویداد یا هر دو اتفاق می‌افتد، حالت کنش متنی را فراخوانی می‌کنید:

  • کاربر یک لمس و نگه داشتن روی نما انجام می دهد.
  • کاربر یک چک باکس یا مؤلفه رابط کاربری مشابه را در نما انتخاب می کند.

اینکه چگونه برنامه شما حالت کنش متنی را فراخوانی می کند و رفتار هر عمل را تعریف می کند به طراحی شما بستگی دارد. دو طرح وجود دارد:

  • برای کنش‌های زمینه‌ای روی دیدگاه‌های فردی و دلبخواه.
  • برای کنش‌های متنی دسته‌ای روی گروه‌هایی از آیتم‌ها در RecyclerView ، به کاربر اجازه می‌دهد چندین آیتم را انتخاب کند و روی همه آنها یک عمل انجام دهد.

بخش های زیر تنظیمات مورد نیاز برای هر سناریو را شرح می دهد.

حالت کنش متنی را برای نماهای فردی فعال کنید

اگر می خواهید حالت کنش متنی را فقط زمانی که کاربر نماهای خاصی را انتخاب می کند فراخوانی کنید، موارد زیر را انجام دهید:

  1. رابط ActionMode.Callback را همانطور که در مثال زیر نشان داده شده است پیاده سازی کنید. در روش‌های برگشت به تماس آن، می‌توانید اقدامات مربوط به نوار اقدام متنی را مشخص کنید، به رویدادهای کلیک روی موارد اقدام پاسخ دهید، و سایر رویدادهای چرخه حیات را برای حالت عمل مدیریت کنید.

    کاتلین

        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
            }
        }
        

    جاوا

        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 مرتبط با رویداد را نیز ارسال می‌کنند. می‌توانید از APIهای ActionMode برای ایجاد تغییرات مختلف در CAB استفاده کنید، مانند اصلاح عنوان و زیرنویس با setTitle() و setSubtitle() که برای نشان دادن تعداد موارد انتخاب شده مفید است.

    نمونه قبلی متغیر actionMode را زمانی که حالت عمل از بین می‌رود، null می‌کند. در مرحله بعد، ببینید که چگونه مقداردهی اولیه می شود و ذخیره متغیر عضو در اکتیویتی یا قطعه شما چقدر می تواند مفید باشد.

  2. هنگامی که می‌خواهید نوار را نشان دهید، مثلاً زمانی که کاربر روی نما لمس می‌کند و نگه می‌دارد، startActionMode() را فراخوانی کنید.

    کاتلین

        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
            }
        }
        

    جاوا

        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 را نشان می‌دهد که به دکمه سرریز در بالا سمت راست متصل شده است.
شکل 4. یک منوی بازشو در برنامه Gmail، که به دکمه سرریز در گوشه سمت راست بالا متصل شده است.

PopupMenu یک منوی معین است که به یک View متصل شده است. در صورت وجود اتاق در زیر نمای لنگر یا در غیر این صورت در بالای نمای ظاهر می شود. برای موارد زیر مفید است:

  • ارائه یک منو به سبک سرریز برای اقدامات مربوط به محتوای خاص، مانند سرصفحه های ایمیل Gmail، نشان داده شده در شکل 4.
  • ارائه بخش دوم یک جمله دستوری، مانند دکمه ای با علامت Add که یک منوی بازشو با گزینه های مختلف Add ایجاد می کند.
  • ارائه منویی شبیه به Spinner که یک انتخاب دائمی را حفظ نمی کند.

اگر منوی خود را در XML تعریف می کنید، در اینجا می توانید منوی بازشو را نشان دهید:

  1. یک PopupMenu با سازنده آن، که Context برنامه فعلی و View که منو به آن متصل است، می گیرد، نمونه سازی کنید.
  2. از MenuInflater استفاده کنید تا منبع منوی خود را به شی Menu که توسط PopupMenu.getMenu() برگردانده شده است، اضافه کنید.
  3. 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" />

سپس اکتیویتی می تواند منوی بازشو را به این صورت نشان دهد:

کاتلین

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()
}

جاوا

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 را اجرا کنید و با فراخوانی setOnMenuItemclickListener() آن را در PopupMenu خود ثبت کنید. هنگامی که کاربر یک مورد را انتخاب می کند، سیستم در رابط کاربری شما، onMenuItemClick() را فراخوانی می کند.

این در مثال زیر نشان داده شده است:

کاتلین

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
    }
}

جاوا

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. یک منوی فرعی با موارد قابل بررسی.

یک منو می‌تواند به عنوان رابطی برای روشن و خاموش کردن گزینه‌ها، استفاده از یک چک باکس برای گزینه‌های مستقل، یا دکمه‌های رادیویی برای گروه‌هایی از گزینه‌های منحصربفرد مفید باشد. شکل 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() تنظیم کنید. این در مثال زیر نشان داده شده است:

کاتلین

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)
    }
}

جاوا

@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 را با startActivity() در طول روش پاسخ به پاسخ مناسب انتخاب‌شده در مورد، مانند callback onOptionsItemSelected() اجرا کنید.

با این حال، اگر مطمئن نیستید که دستگاه کاربر دارای برنامه‌ای است که هدف را مدیریت می‌کند، افزودن یک آیتم منو که آن را فراخوانی می‌کند می‌تواند منجر به یک آیتم منو ناکارآمد شود، زیرا ممکن است هدف به یک فعالیت تبدیل نشود. برای حل این مشکل، Android به شما امکان می‌دهد به صورت پویا آیتم‌های منو را زمانی که Android فعالیت‌هایی را در دستگاهی پیدا می‌کند که هدف شما را مدیریت می‌کند، به منوی خود اضافه کنید.

برای افزودن آیتم های منو بر اساس فعالیت های موجود که یک intent را می پذیرند، موارد زیر را انجام دهید:

  1. یک هدف را با دسته CATEGORY_ALTERNATIVE یا CATEGORY_SELECTED_ALTERNATIVE ، یا هر دو، به‌علاوه هر الزام دیگر تعریف کنید.
  2. فراخوانی Menu.addIntentOptions() . سپس اندروید هر برنامه‌ای را که بتواند این هدف را انجام دهد جستجو می‌کند و آنها را به منوی شما اضافه می‌کند.

اگر هیچ برنامه‌ای نصب نشده باشد که هدف را برآورده کند، هیچ آیتم منو اضافه نمی‌شود.

این در مثال زیر نشان داده شده است:

کاتلین

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
}

جاوا

@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 intent به عنوان عنوان آیتم منو و نماد برنامه به عنوان نماد آیتم منو. متد 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>

درباره نوشتن فیلترهای هدف در Intent و فیلترهای هدف بیشتر بخوانید.