เมนูเป็นองค์ประกอบของอินเทอร์เฟซผู้ใช้ที่พบได้ทั่วไปในแอปหลายประเภท ถึง
ให้ประสบการณ์ของผู้ใช้ที่คุ้นเคยและสอดคล้องกัน
Menu
API ไปยัง
แสดงการดำเนินการของผู้ใช้และตัวเลือกอื่นๆ ในกิจกรรมของคุณ
เอกสารนี้จะแสดงวิธีสร้างเมนูพื้นฐาน 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" "เขียนอีเมล" และ "การตั้งค่า"
คุณสามารถประกาศรายการสำหรับเมนูตัวเลือกจาก
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()
สร้างเมนูตามบริบท
เมนูตามบริบทมีการดำเนินการที่ส่งผลต่อรายการหรือบริบทที่เจาะจง
ใน UI คุณสามารถระบุเมนูตามบริบทสำหรับมุมมองใดก็ได้
ซึ่งมักใช้สำหรับรายการใน
RecylerView
หรือ
คอลเล็กชันข้อมูลพร็อพเพอร์ตี้อื่นๆ ที่ผู้ใช้สามารถดำเนินการได้โดยตรงในแต่ละรายการ
รายการ
การดำเนินการตามบริบททำได้ 2 วิธีดังนี้
- ในเมนูตามบริบทแบบลอย เมนู ปรากฏเป็นรายการแบบลอยของรายการในเมนู คล้ายกับกล่องโต้ตอบ เมื่อ ผู้ใช้แตะและ คงการแสดงผลไว้ซึ่งประกาศการรองรับบริบท เมนู ผู้ใช้จะดำเนินการตามบริบทกับแต่ละรายการได้ทีละรายการ
- ในโหมดการดำเนินการตามบริบท โหมดนี้เป็นระบบ
การใช้งาน
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
ให้คุณเพิ่มเมนูตามบริบทจากแหล่งข้อมูลเมนูได้ เมธอด Callback จะมี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
ถ้า คุณไม่ได้จัดการรายการในเมนู ส่งรายการในเมนูไปยัง Superclass การใช้งานของคุณ ถ้ากิจกรรมของคุณมีส่วนย่อย กิจกรรมจะได้รับ Callback นี้ก่อน การเรียก Superclass เมื่อไม่มีการจัดการ จะทำให้ระบบ ส่งต่อเหตุการณ์ไปยังเมธอด Callback ที่เกี่ยวข้องในแต่ละ Fragment ที่ ตามลำดับการเพิ่มในแต่ละแฟรกเมนต์ จนถึงtrue
หรือ ระบบส่งกลับfalse
การติดตั้งใช้งานเริ่มต้นสำหรับActivity
และandroid.app.Fragment
รีเทิร์นfalse
ดังนั้นโปรดเรียก Superclass เมื่อไม่มีการจัดการเสมอ
ใช้โหมดการดำเนินการตามบริบท
โหมดการดำเนินการตามบริบทคือการใช้งานระบบของ
ActionMode
ที่มุ่งเน้นการโต้ตอบกับผู้ใช้ต่อการแสดง
การดำเนินการตามบริบท เมื่อผู้ใช้เปิดใช้โหมดนี้โดยการเลือกรายการ
แถบการดำเนินการตามบริบทจะปรากฏที่ด้านบนของหน้าจอเพื่อนำเสนอ
สิ่งที่ผู้ใช้ทำได้กับรายการที่เลือก ขณะที่เปิดใช้โหมดนี้
ผู้ใช้สามารถเลือกหลายรายการได้ หากแอปของคุณรองรับ และสามารถยกเลิกการเลือก
รายการและไปยังส่วนต่างๆ ภายในกิจกรรมต่อไป โหมดการทำงานปิดอยู่
และแถบการดำเนินการตามบริบทจะหายไปเมื่อผู้ใช้ยกเลิกการเลือกรายการทั้งหมด
แตะปุ่มย้อนกลับ หรือแตะการทำงานเสร็จสิ้นทางด้านซ้ายของแท็ก
แถบ
สำหรับข้อมูลพร็อพเพอร์ตี้ที่มีการทำงานตามบริบท คุณมักจะเรียกใช้ฟังก์ชัน โหมดการทำงานเมื่อเกิดเหตุการณ์ 1 หรือทั้ง 2 เหตุการณ์ต่อไปนี้
- ผู้ใช้แตะและ ค้างไว้ที่มุมมอง
- ผู้ใช้เลือกช่องทำเครื่องหมายหรือคอมโพเนนต์ UI ที่คล้ายกันภายในมุมมอง
วิธีที่แอปเรียกใช้โหมดการดำเนินการตามบริบทและกำหนด สำหรับการดำเนินการแต่ละอย่างนั้นจะขึ้นอยู่กับการออกแบบของคุณ มีการออกแบบ 2 แบบ ดังนี้
- สำหรับการดำเนินการตามบริบทของมุมมองที่กำหนดเอง
- สำหรับการดำเนินการตามบริบทแบบกลุ่มกับรายการใน
RecyclerView
ให้ผู้ใช้เลือกได้หลายรายการและ ดำเนินการกับพวกเขาทั้งหมด
ส่วนต่อไปนี้จะอธิบายการตั้งค่าที่จําเป็นสําหรับแต่ละสถานการณ์
เปิดใช้โหมดการทำงานตามบริบทสำหรับแต่ละมุมมอง
หากต้องการเรียกใช้โหมดการทำงานตามบริบทเฉพาะเมื่อผู้ใช้เลือก โดยเลือกทำสิ่งต่อไปนี้
- ใช้อินเทอร์เฟซ
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
เมื่อโหมดการดำเนินการถูกทำลาย ในขั้นตอนถัดไป ให้ดู เริ่มต้นอย่างไร บันทึกตัวแปรสมาชิกอย่างไรในกิจกรรม หรือ ส่วนย่อยอาจมีประโยชน์ - โทร
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
โดยจะปรากฏใต้โฆษณา Anchor
ดูว่ามีพื้นที่ว่างเพียงพอหรืออยู่เหนือมุมมองหรือไม่ ซึ่งมีประโยชน์สำหรับ
ดังต่อไปนี้:
- การให้เมนูรูปแบบเพิ่มเติมสำหรับการดำเนินการที่เกี่ยวข้องกับ เนื้อหาเฉพาะ เช่น ส่วนหัวอีเมลของ Gmail ดังแสดงในรูปที่ 4
- การระบุส่วนที่ 2 ของประโยคคำสั่ง เช่น ปุ่มที่มีเครื่องหมาย เพิ่ม ที่สร้างเมนูป๊อปอัปที่มีปุ่มเพิ่ม ตัวเลือก
- การจัดเตรียมเมนูที่คล้ายกับ
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()
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 แสดงเมนูย่อยที่มีรายการที่ตรวจสอบได้ด้วย ปุ่มตัวเลือก
คุณสามารถกำหนดลักษณะการทำงานที่ตรวจสอบได้สำหรับรายการในเมนูแต่ละรายการโดยใช้
แอตทริบิวต์ 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 พบกิจกรรมในอุปกรณ์ที่จัดการความตั้งใจของคุณ
หากต้องการเพิ่มรายการในเมนูโดยอิงตามกิจกรรมที่มีซึ่งยอมรับความตั้งใจ ให้ทำ ดังต่อไปนี้
- ระบุ Intent ด้วยหมวดหมู่
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 ที่ตรงกับ 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 ตัวกรอง