เพิ่มเมนู

ลองใช้วิธีการเขียน
Jetpack Compose เป็นชุดเครื่องมือ UI ที่แนะนำสำหรับ Android ดูวิธีเพิ่มคอมโพเนนต์ใน Compose

เมนูเป็นองค์ประกอบของอินเทอร์เฟซผู้ใช้ที่พบได้ทั่วไปในแอปหลายประเภท ถึง ให้ประสบการณ์ของผู้ใช้ที่คุ้นเคยและสอดคล้องกัน Menu API ไปยัง แสดงการดำเนินการของผู้ใช้และตัวเลือกอื่นๆ ในกิจกรรมของคุณ

รูปภาพแสดงตัวอย่างเมนูรายการเพิ่มเติม
รูปที่ 1 เมนูที่ทริกเกอร์โดยการแตะไอคอน ที่ปรากฏด้านล่างไอคอนเมนูรายการเพิ่มเติม

เอกสารนี้จะแสดงวิธีสร้างเมนูพื้นฐาน 3 ประเภท หรือ การนำเสนอการดำเนินการใน Android ทุกเวอร์ชัน

เมนูตัวเลือกและแถบแอป
เมนูตัวเลือกคือคอลเล็กชันหลักของรายการในเมนูสำหรับ กิจกรรม เป็นที่ที่คุณวางการดำเนินการที่มีผลกระทบทั่วโลกต่อ เช่น "Search" "เขียนอีเมล" และ "การตั้งค่า"

ดูเมนูสร้างตัวเลือก

เมนูตามบริบทและโหมดการดำเนินการตามบริบท
เมนูตามบริบทเป็นเมนูแบบลอย ที่ปรากฏเมื่อผู้ใช้แตะและ ค้างไว้ 1 องค์ประกอบ ทั้งนี้ ระบุการดำเนินการที่ส่งผลต่อเนื้อหาหรือกรอบบริบทที่เลือก

โหมดการดำเนินการตามบริบทจะแสดงรายการการทำงานที่ มีผลต่อเนื้อหาที่เลือกในแถบที่ด้านบนของหน้าจอ และจะทำให้ ที่ผู้ใช้เลือกหลายรายการ

โปรดดูส่วนสร้างเมนูตามบริบท

เมนูป๊อปอัป
เมนูป๊อปอัปแสดงรายการในแนวตั้งซึ่งตรึงอยู่กับ ที่เรียกเมนู เหมาะสำหรับการเพิ่มการดำเนินการเพิ่มเติม ที่เกี่ยวข้องกับเนื้อหาเฉพาะหรือเพื่อให้ตัวเลือกของส่วนที่ 2 ตามคำสั่ง การทำงานในเมนูป๊อปอัปจะไม่ส่งผลกระทบต่อ เนื้อหาที่สอดคล้องกัน นั่นเป็นเพราะการดำเนินการตามบริบท แต่เป็น เมนูป๊อปอัปมีไว้สำหรับการทำงานเพิ่มเติมที่เกี่ยวข้องกับภูมิภาคของเนื้อหาใน กิจกรรมของคุณ

ดูส่วนสร้างเมนูป๊อปอัป

กำหนดเมนูใน XML

สำหรับเมนูทุกประเภท Android ให้รูปแบบ XML มาตรฐานในการกำหนดเมนู รายการ แทนที่จะสร้างเมนูในโค้ดของกิจกรรม ให้กำหนดเมนูและ ทุกรายการใน XML แหล่งข้อมูลเมนู คุณสามารถ จากนั้นขยายทรัพยากรเมนูให้สูงเกินจริง ซึ่งจะโหลดเป็น Menu ในกิจกรรมหรือส่วนย่อย

การใช้แหล่งข้อมูลเมนูเป็นแนวทางปฏิบัติที่ดีเนื่องจากเหตุผลต่อไปนี้

  • ทำให้เห็นภาพโครงสร้างเมนูใน XML ได้ง่ายกว่า
  • ช่วยแยกเนื้อหาสำหรับเมนูออกจากพฤติกรรมของแอป โค้ด
  • ให้คุณสร้างการกำหนดค่าเมนูสำรองสำหรับแพลตฟอร์มต่างๆ เวอร์ชัน ขนาดหน้าจอ และการกำหนดค่าอื่นๆ โดยใช้ประโยชน์จาก แหล่งข้อมูลของแอป

หากต้องการกำหนดเมนู ให้สร้างไฟล์ XML ภายใน ไดเรกทอรี res/menu/ และสร้างเมนูด้วยข้อมูลต่อไปนี้ องค์ประกอบ:

<menu>
กำหนด Menu ซึ่งเป็นคอนเทนเนอร์สำหรับรายการในเมนู ต เอลิเมนต์ <menu> ต้องเป็นโหนดรากของไฟล์ และ จะเก็บ <item> และ <group> ได้อย่างน้อย 1 รายการ จากองค์ประกอบเหล่านี้
<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> เมนูย่อยจะมีประโยชน์เมื่อแอปมีฟังก์ชันมากมายที่สามารถจัดระเบียบได้ เป็นหัวข้อต่างๆ เช่น รายการในแถบเมนูของแอป PC เช่น ไฟล์ แก้ไข และดู โปรดดูตัวอย่างต่อไปนี้

<?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 คือ การทำงานและตัวเลือกอื่นๆ ที่เกี่ยวข้องกับบริบทกิจกรรมปัจจุบัน เช่น "Search" "เขียนอีเมล" และ "การตั้งค่า"

วันที่ รูปภาพแสดงแถบแอปสำหรับแอป Google ชีต
รูปที่ 2 แอป Google ชีต แสดง หลายปุ่ม รวมถึงปุ่มการทำงานเพิ่มเติม

คุณสามารถประกาศรายการสำหรับเมนูตัวเลือกจาก Activity คลาสย่อยหรือ วันที่ Fragment คลาสย่อย หากทั้งกิจกรรมและส่วนย่อยของคุณประกาศรายการสำหรับ เมนูตัวเลือก รายการเหล่านี้จะรวมเข้าด้วยกันใน UI รายการของกิจกรรมจะปรากฏขึ้น ก่อนตามด้วยส่วนย่อยของแต่ละส่วนย่อย ตามลำดับที่ส่วนย่อย จะเพิ่มลงในกิจกรรม หากจำเป็น คุณสามารถเรียงลำดับรายการในเมนูใหม่ด้วย แอตทริบิวต์ android:orderInCategory ในแต่ละคอลัมน์ <item>ที่คุณต้องการย้าย

หากต้องการระบุเมนูตัวเลือกสำหรับกิจกรรม ให้ลบล้าง onCreateOptionsMenu() ส่วนย่อยมีเอกลักษณ์เป็นของตัวเอง onCreateOptionsMenu() Callback ในวิธีการนี้ คุณเพิ่มทรัพยากรเมนูให้สูงเกินจริงได้ ที่กำหนดไว้ใน XML ลงใน Menu ที่ระบุไว้ใน Callback ตัวอย่างนี้จะแสดงในตัวอย่างต่อไปนี้

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 API

จัดการกิจกรรมการคลิก

เมื่อผู้ใช้เลือกรายการจากเมนูตัวเลือก รวมถึงรายการการทำงาน ในแถบแอป ระบบจะเรียกใช้ 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 หากคุณ ไม่จัดการรายการเมนู, เรียกการใช้งาน Superclass ของ onOptionsItemSelected() การติดตั้งใช้งานเริ่มต้นจะส่งคืน เท็จ

หากกิจกรรมมีส่วนย่อย ระบบจะเรียกใช้ก่อน onOptionsItemSelected() สำหรับกิจกรรม จากนั้นสำหรับแต่ละส่วนย่อย ตามลำดับการเพิ่มส่วนย่อย จนกว่าจะแสดงผล true หรือ ระบบจะเรียกส่วนย่อยทั้งหมด

เปลี่ยนรายการในเมนูขณะรันไทม์

หลังจากที่ระบบเรียกใช้ onCreateOptionsMenu() แล้ว ระบบจะเก็บรักษา อินสแตนซ์ของ Menu ที่คุณป้อนข้อมูลและไม่ได้เรียกใช้ onCreateOptionsMenu() อีกครั้ง เว้นแต่เมนูจะใช้ไม่ได้ แต่ให้ใช้ onCreateOptionsMenu() เพื่อสร้างเมนูเริ่มต้นเท่านั้น และไม่ทำการเปลี่ยนแปลงในวงจรของกิจกรรม

คุณต้องการแก้ไขเมนูตัวเลือกตามเหตุการณ์ที่เกิดขึ้นระหว่าง ในวงจรของกิจกรรม onPrepareOptionsMenu() เมธอดนี้ส่งออบเจ็กต์ Menu ให้คุณตามเช่นปัจจุบัน มีอยู่ เพื่อให้คุณสามารถแก้ไข เช่น เพิ่ม ลบ หรือปิดใช้รายการ Fragment ยังมี onPrepareOptionsMenu() Callback

เมนูตัวเลือกเปิดตลอดเมื่อมีการแสดงรายการเมนูใน แถบแอป เมื่อมีกิจกรรมเกิดขึ้นและคุณต้องการอัปเดตเมนู โปรดโทร invalidateOptionsMenu() เพื่อขอให้ระบบเรียกใช้ onPrepareOptionsMenu()

สร้างเมนูตามบริบท

วันที่ รูปภาพแสดงเมนูตามบริบทแบบลอย
รูปที่ 3 เมนูตามบริบทแบบลอย

เมนูตามบริบทมีการดำเนินการที่ส่งผลต่อรายการหรือบริบทที่เจาะจง ใน UI คุณสามารถระบุเมนูตามบริบทสำหรับมุมมองใดก็ได้ ซึ่งมักใช้สำหรับรายการใน RecylerView หรือ คอลเล็กชันข้อมูลพร็อพเพอร์ตี้อื่นๆ ที่ผู้ใช้สามารถดำเนินการได้โดยตรงในแต่ละรายการ รายการ

การดำเนินการตามบริบททำได้ 2 วิธีดังนี้

  • ในเมนูตามบริบทแบบลอย เมนู ปรากฏเป็นรายการแบบลอยของรายการในเมนู คล้ายกับกล่องโต้ตอบ เมื่อ ผู้ใช้แตะและ คงการแสดงผลไว้ซึ่งประกาศการรองรับบริบท เมนู ผู้ใช้จะดำเนินการตามบริบทกับแต่ละรายการได้ทีละรายการ
  • ในโหมดการดำเนินการตามบริบท โหมดนี้เป็นระบบ การใช้งาน ActionMode ซึ่งแสดงแถบการดำเนินการตามบริบทหรือ CAB ที่ด้านบนของ หน้าจอแสดงรายการการทำงานที่ส่งผลต่อรายการที่เลือก เมื่ออยู่ในโหมดนี้ ทำงานอยู่ ผู้ใช้สามารถดำเนินการหลายรายการพร้อมกันได้ หาก ก็ทำได้ทั้งนั้น

หมายเหตุ: เมนูตามบริบทไม่รองรับทางลัดรายการและไอคอนรายการ

สร้างเมนูตามบริบทแบบลอย

ในการสร้างเมนูตามบริบทแบบลอย ให้ทำดังนี้

  1. ลงทะเบียน View ที่เชื่อมโยงกับเมนูตามบริบท การโทร วันที่ registerForContextMenu() และส่ง View

    หากกิจกรรมของคุณใช้ RecyclerView และคุณต้องการให้แต่ละกิจกรรม รายการที่จะให้บริบทเดียวกัน โปรดลงทะเบียนรายการทั้งหมดสำหรับบริบท โดยส่ง RecyclerView ไปยัง registerForContextMenu()

  2. ติดตั้งใช้งาน 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 ให้คุณเพิ่มเมนูตามบริบทจากแหล่งข้อมูลเมนูได้ เมธอด Callback จะมี View ที่ผู้ใช้เลือกและ วันที่ ContextMenu.ContextMenuInfo ที่ให้ข้อมูลเพิ่มเติมเกี่ยวกับรายการที่เลือก ถ้า กิจกรรมของคุณมีหลายมุมมอง โดยแต่ละรายการมีเมนูตามบริบทที่แตกต่างกัน คุณอาจใช้พารามิเตอร์เหล่านี้เพื่อกำหนดเมนูตามบริบทที่จะ พอง

  3. ใช้งาน 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 ถ้า คุณไม่ได้จัดการรายการในเมนู ส่งรายการในเมนูไปยัง Superclass การใช้งานของคุณ ถ้ากิจกรรมของคุณมีส่วนย่อย กิจกรรมจะได้รับ Callback นี้ก่อน การเรียก Superclass เมื่อไม่มีการจัดการ จะทำให้ระบบ ส่งต่อเหตุการณ์ไปยังเมธอด Callback ที่เกี่ยวข้องในแต่ละ Fragment ที่ ตามลำดับการเพิ่มในแต่ละแฟรกเมนต์ จนถึง true หรือ ระบบส่งกลับ false การติดตั้งใช้งานเริ่มต้นสำหรับ Activity และ android.app.Fragment รีเทิร์น false ดังนั้นโปรดเรียก Superclass เมื่อไม่มีการจัดการเสมอ

ใช้โหมดการดำเนินการตามบริบท

โหมดการดำเนินการตามบริบทคือการใช้งานระบบของ ActionMode ที่มุ่งเน้นการโต้ตอบกับผู้ใช้ต่อการแสดง การดำเนินการตามบริบท เมื่อผู้ใช้เปิดใช้โหมดนี้โดยการเลือกรายการ แถบการดำเนินการตามบริบทจะปรากฏที่ด้านบนของหน้าจอเพื่อนำเสนอ สิ่งที่ผู้ใช้ทำได้กับรายการที่เลือก ขณะที่เปิดใช้โหมดนี้ ผู้ใช้สามารถเลือกหลายรายการได้ หากแอปของคุณรองรับ และสามารถยกเลิกการเลือก รายการและไปยังส่วนต่างๆ ภายในกิจกรรมต่อไป โหมดการทำงานปิดอยู่ และแถบการดำเนินการตามบริบทจะหายไปเมื่อผู้ใช้ยกเลิกการเลือกรายการทั้งหมด แตะปุ่มย้อนกลับ หรือแตะการทำงานเสร็จสิ้นทางด้านซ้ายของแท็ก แถบ

สำหรับข้อมูลพร็อพเพอร์ตี้ที่มีการทำงานตามบริบท คุณมักจะเรียกใช้ฟังก์ชัน โหมดการทำงานเมื่อเกิดเหตุการณ์ 1 หรือทั้ง 2 เหตุการณ์ต่อไปนี้

  • ผู้ใช้แตะและ ค้างไว้ที่มุมมอง
  • ผู้ใช้เลือกช่องทำเครื่องหมายหรือคอมโพเนนต์ UI ที่คล้ายกันภายในมุมมอง

วิธีที่แอปเรียกใช้โหมดการดำเนินการตามบริบทและกำหนด สำหรับการดำเนินการแต่ละอย่างนั้นจะขึ้นอยู่กับการออกแบบของคุณ มีการออกแบบ 2 แบบ ดังนี้

  • สำหรับการดำเนินการตามบริบทของมุมมองที่กำหนดเอง
  • สำหรับการดำเนินการตามบริบทแบบกลุ่มกับรายการใน RecyclerView ให้ผู้ใช้เลือกได้หลายรายการและ ดำเนินการกับพวกเขาทั้งหมด

ส่วนต่อไปนี้จะอธิบายการตั้งค่าที่จําเป็นสําหรับแต่ละสถานการณ์

เปิดใช้โหมดการทำงานตามบริบทสำหรับแต่ละมุมมอง

หากต้องการเรียกใช้โหมดการทำงานตามบริบทเฉพาะเมื่อผู้ใช้เลือก โดยเลือกทำสิ่งต่อไปนี้

  1. ใช้อินเทอร์เฟซ ActionMode.Callback ตามที่แสดงใน ดังตัวอย่างต่อไปนี้ ในเมธอด 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;
            }
        };
        

    Callback ของเหตุการณ์เหล่านี้แทบจะเหมือนกันทุกประการกับ Callback สำหรับ เมนูตัวเลือก เว้นแต่ว่า ส่งผ่านออบเจ็กต์ ActionMode ที่เชื่อมโยงกับเหตุการณ์ด้วย คุณใช้ ActionMode API เพื่อทำการเปลี่ยนแปลงต่างๆ ได้ CAB เช่น การแก้ไขชื่อและคำบรรยายด้วย วันที่ setTitle() และ setSubtitle(), ซึ่งมีประโยชน์ในการบอกจำนวนรายการที่เลือก

    ตัวอย่างก่อนหน้านี้ตั้งค่าตัวแปร actionMode เป็น null เมื่อโหมดการดำเนินการถูกทำลาย ในขั้นตอนถัดไป ให้ดู เริ่มต้นอย่างไร บันทึกตัวแปรสมาชิกอย่างไรในกิจกรรม หรือ ส่วนย่อยอาจมีประโยชน์

  2. โทร 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 ซึ่งตรึงอยู่กับปุ่มรายการเพิ่มเติมที่ด้านขวาบน
รูปที่ 4 เมนูป๊อปอัปในแอป Gmail โดยจะยึดอยู่กับปุ่มรายการเพิ่มเติมที่มุมบนขวา

PopupMenu เป็นเมนูโมดัลที่ตรึงอยู่กับ View โดยจะปรากฏใต้โฆษณา Anchor ดูว่ามีพื้นที่ว่างเพียงพอหรืออยู่เหนือมุมมองหรือไม่ ซึ่งมีประโยชน์สำหรับ ดังต่อไปนี้:

  • การให้เมนูรูปแบบเพิ่มเติมสำหรับการดำเนินการที่เกี่ยวข้องกับ เนื้อหาเฉพาะ เช่น ส่วนหัวอีเมลของ Gmail ดังแสดงในรูปที่ 4
  • การระบุส่วนที่ 2 ของประโยคคำสั่ง เช่น ปุ่มที่มีเครื่องหมาย เพิ่ม ที่สร้างเมนูป๊อปอัปที่มีปุ่มเพิ่ม ตัวเลือก
  • การจัดเตรียมเมนูที่คล้ายกับ 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" />

จากนั้นกิจกรรมจะแสดงเมนูป๊อปอัปในลักษณะต่อไปนี้

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() Callback ในอินเทอร์เฟซของคุณ

ตัวอย่างนี้จะแสดงในตัวอย่างต่อไปนี้

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>

รายการที่อยู่ในกลุ่มจะปรากฏที่ระดับเดียวกับรายการแรก รายการ ทั้ง 3 รายการในเมนูเป็นรายการข้างเคียง อย่างไรก็ตาม คุณสามารถแก้ไข ลักษณะของทั้ง 2 รายการในกลุ่มโดยอ้างอิงรหัสกลุ่มและใช้ วิธีการก่อนหน้านี้ นอกจากนี้ ระบบจะไม่แยกรายการที่จัดกลุ่มไว้อีกด้วย สำหรับ เช่น หากประกาศ 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
เลือกรายการจากกลุ่มได้เพียง 1 รายการเท่านั้น ซึ่งจะส่งผลให้เป็นวิทยุ
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 วันที่ startActivity() ในระหว่างเมธอด Callback ที่เลือกในรายการที่เหมาะสม เช่น onOptionsItemSelected() Callback

แต่ถ้าคุณไม่แน่ใจว่าอุปกรณ์ของผู้ใช้มีแอปที่ จัดการ Intent การเพิ่มรายการในเมนูที่เรียกใช้ อาจส่งผลให้เกิด รายการเมนูที่ไม่ทำงาน เนื่องจาก Intent อาจไม่เปลี่ยนเป็นกิจกรรม เพื่อแก้ปัญหานี้ Android จึงให้คุณเพิ่มรายการในเมนูแบบไดนามิกในเมนูเมื่อ Android พบกิจกรรมในอุปกรณ์ที่จัดการความตั้งใจของคุณ

หากต้องการเพิ่มรายการในเมนูโดยอิงตามกิจกรรมที่มีซึ่งยอมรับความตั้งใจ ให้ทำ ดังต่อไปนี้

  1. ระบุ Intent ด้วยหมวดหมู่ CATEGORY_ALTERNATIVE หรือ CATEGORY_SELECTED_ALTERNATIVE, หรือทั้งสองอย่าง รวมถึงข้อกำหนดอื่นๆ
  2. โทร 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 ที่ตรงกับ Intent จะมีการเพิ่มรายการในเมนู โดยใช้ค่าในคอลัมน์ Intent android:label เป็นชื่อรายการเมนู และใช้ไอคอนแอปเป็นเมนู ไอคอนรายการ เมธอด addIntentOptions() จะแสดงผลจำนวนของ เพิ่มรายการในเมนูแล้ว

อนุญาตให้เพิ่มกิจกรรมในเมนูอื่นๆ

คุณสามารถเสนอกิจกรรมที่คุณทำให้แก่แอปอื่นๆ ได้ เพื่อให้แอปของคุณสามารถ รวมอยู่ในเมนูของผู้อื่น การกลับบทบาทที่อธิบายไว้ก่อนหน้านี้

หากต้องการรวมอยู่ในเมนูอื่นๆ ของแอป ให้กำหนดตัวกรอง Intent ตามปกติ แต่ใส่ CATEGORY_ALTERNATIVE หรือ CATEGORY_SELECTED_ALTERNATIVE ค่า หรือทั้ง 2 ค่าสำหรับ Intent หมวดหมู่ตัวกรอง ตัวอย่างนี้จะแสดงในตัวอย่างต่อไปนี้

<intent-filter label="@string/resize_image">
    ...
    <category android:name="android.intent.category.ALTERNATIVE" />
    <category android:name="android.intent.category.SELECTED_ALTERNATIVE" />
    ...
</intent-filter>

อ่านเพิ่มเติมเกี่ยวกับการเขียนตัวกรอง Intent ใน Intent และ Intent ตัวกรอง