Trình đơn là thành phần giao diện người dùng phổ biến trong nhiều loại ứng dụng. Người nhận
mang lại trải nghiệm người dùng quen thuộc và nhất quán, hãy sử dụng
Menu
API đến
hiển thị hành động của người dùng và các tuỳ chọn khác trong hoạt động của bạn.
Tài liệu này trình bày cách tạo 3 loại trình đơn hoặc bản trình bày hành động trên mọi phiên bản Android:
- Trình đơn tùy chọn và thanh ứng dụng
- Trình đơn tuỳ chọn là tập hợp chính gồm các mục trong trình đơn cho
của bạn. Đây là nơi bạn đặt ra các hành động có tác động chung đến
ứng dụng, chẳng hạn như "Tìm kiếm", "Soạn email", và "Cài đặt".
Xem trình đơn Tạo tuỳ chọn .
- Trình đơn theo bối cảnh và chế độ thao tác theo bối cảnh
- Trình đơn theo bối cảnh là một trình đơn nổi
xuất hiện khi người dùng thực hiện thao tác chạm và giữ một phần tử. Nó
cung cấp các thao tác ảnh hưởng đến nội dung hoặc khung ngữ cảnh đã chọn.
Chế độ thao tác theo ngữ cảnh hiển thị các mục hành động ảnh hưởng đến nội dung đã chọn trên thanh ở đầu màn hình và cho phép người dùng chọn nhiều mục.
Hãy xem phần Tạo trình đơn theo ngữ cảnh .
- Trình đơn bật lên
- Trình đơn bật lên hiển thị danh sách các mục theo chiều dọc được liên kết với
khung hiển thị gọi trình đơn. Thật hữu ích khi cung cấp nhiều thao tác
liên quan đến nội dung cụ thể hoặc để cung cấp các tuỳ chọn cho phần thứ hai
của một lệnh. Các thao tác trong trình đơn bật lên không ảnh hưởng trực tiếp đến
nội dung tương ứng — đó chính là mục đích của các thao tác theo ngữ cảnh. Thay vào đó,
trình đơn bật lên dành cho các thao tác mở rộng có liên quan đến các vùng nội dung trong
hoạt động của bạn.
Xem phần Tạo trình đơn bật lên.
Xác định trình đơn trong XML
Đối với mọi loại trình đơn, Android cung cấp một định dạng XML tiêu chuẩn để xác định trình đơn
mục. Thay vì tạo trình đơn trong mã của hoạt động, hãy xác định một trình đơn và
tất cả các mục trong tệp XML
tài nguyên trình đơn. Bạn có thể
rồi tăng cường tài nguyên trình đơn – tải nó dưới dạng Menu
đối tượng – trong hoạt động hoặc mảnh của bạn.
Bạn nên sử dụng tài nguyên trình đơn vì những lý do sau:
- Dễ dàng hình ảnh hóa cấu trúc trình đơn ở định dạng XML hơn.
- Lớp này tách nội dung của trình đơn khỏi hành vi của ứng dụng .
- Trình đơn này cho phép bạn tạo các cấu hình trình đơn thay thế cho nền tảng khác nhau phiên bản, kích thước màn hình và các cấu hình khác bằng cách tận dụng tài nguyên ứng dụng khung.
Để xác định trình đơn, hãy tạo một tệp XML bên trong
Thư mục res/menu/
và xây dựng trình đơn bằng các thành phần sau
phần tử:
<menu>
- Xác định
Menu
, là một vùng chứa các mục trong trình đơn. Đáp Phần tử<menu>
phải là nút gốc của tệp và nó có thể lưu một hoặc nhiều<item>
và<group>
phần tử. <item>
- Tạo một
MenuItem
, đại diện cho một mục trong trình đơn. Phần tử này có thể chứa một phần tử lồng nhau Phần tử<menu>
để tạo trình đơn phụ. <group>
- Một vùng chứa không bắt buộc, ẩn dành cho
<item>
phần tử. Tính năng này cho phép bạn phân loại các mục trong trình đơn để chúng dùng chung thuộc tính, chẳng hạn như làm trạng thái hoạt động và chế độ hiển thị. Để biết thêm thông tin, hãy xem Mục Tạo một nhóm thực đơn.
Trình đơn mẫu có tên là 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>
Phần tử <item>
hỗ trợ một số thuộc tính mà bạn có thể dùng
để xác định giao diện và hành vi của một mục. Các mục trong trình đơn trước
bao gồm các thuộc tính sau:
android:id
- Mã tài nguyên dành riêng cho mục, cho phép ứng dụng nhận ra mặt hàng khi người dùng chọn.
android:icon
- Tham chiếu đến đối tượng có thể vẽ để sử dụng làm biểu tượng của mục.
android:title
- Tham chiếu đến một chuỗi dùng làm tiêu đề mục.
android:showAsAction
- Thông số kỹ thuật về thời điểm và cách thức mục này xuất hiện dưới dạng mục hành động trong thanh ứng dụng.
Đây là những thuộc tính quan trọng nhất mà bạn sử dụng, nhưng vẫn còn nhiều thuộc tính khác sẵn có. Để biết thông tin về tất cả các thuộc tính được hỗ trợ, hãy xem Tài nguyên trình đơn tài liệu.
Bạn có thể thêm trình đơn phụ vào một mục trong bất kỳ trình đơn nào bằng cách thêm
Phần tử <menu>
làm phần tử con của <item>
.
Trình đơn phụ rất hữu ích khi ứng dụng có thể sắp xếp được nhiều chức năng
vào chủ đề, như các mục trong thanh trình đơn của ứng dụng trên máy tính—chẳng hạn như Tệp,
Chỉnh sửa và Xem. Hãy xem ví dụ sau:
<?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>
Để sử dụng trình đơn trong hoạt động của bạn, hãy _inflate_ tài nguyên trình đơn, chuyển đổi
tài nguyên XML vào một đối tượng có thể lập trình được bằng cách sử dụng
MenuInflater.inflate()
.
Các phần sau đây cho biết cách mở rộng trình đơn cho từng loại trình đơn.
Tạo trình đơn tuỳ chọn
Trình đơn tuỳ chọn (như trình đơn minh hoạ trong hình 1) là nơi bạn bao gồm các hành động và tuỳ chọn khác có liên quan đến bối cảnh hoạt động hiện tại, chẳng hạn như "Tìm kiếm", "Soạn email", và "Cài đặt".
Bạn có thể khai báo các mục cho trình đơn tuỳ chọn từ
Activity
lớp con hoặc một
Fragment
lớp con. Nếu cả hoạt động và mảnh đều khai báo các mục cho
trình đơn tuỳ chọn, các mục sẽ được kết hợp trong giao diện người dùng. Các mục của hoạt động xuất hiện
đầu tiên, sau đó là các phân đoạn của từng mảnh, theo thứ tự các phân đoạn
sẽ được thêm vào hoạt động. Nếu cần, bạn có thể sắp xếp lại các mục trong trình đơn với
thuộc tính android:orderInCategory
trong mỗi
<item>
bạn cần di chuyển.
Để chỉ định trình đơn tuỳ chọn cho một hoạt động, hãy ghi đè
onCreateOptionsMenu()
.
Các mảnh tự cung cấp dữ liệu
onCreateOptionsMenu()
. Trong phương pháp này, bạn có thể tăng cường tài nguyên trình đơn,
được xác định trong XML, vào Menu
được cung cấp trong
. Lệnh này được minh hoạ trong ví dụ sau:
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; }
Bạn cũng có thể thêm các món trong thực đơn bằng cách sử dụng
add()
và truy xuất các mục bằng
findItem()
để sửa đổi thuộc tính bằng API MenuItem
.
Xử lý các sự kiện nhấp chuột
Khi người dùng chọn một mục trong trình đơn tuỳ chọn, bao gồm cả các mục hành động
trong thanh ứng dụng, hệ thống sẽ gọi
onOptionsItemSelected()
. Phương thức này truyền tham số MenuItem
đã chọn. Bạn có thể xác định
mặt hàng bằng cách gọi
getItemId()
,
Hàm này trả về mã nhận dạng duy nhất cho mục trong trình đơn, được xác định bởi
Thuộc tính android:id
trong tài nguyên trình đơn hoặc với một số nguyên đã cho
cho phương thức add()
. Bạn có thể so khớp mã này với trình đơn đã biết
để thực hiện hành động thích hợp.
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); } }
Khi xử lý thành công một mục trong trình đơn, hãy trả lại true
. Nếu bạn
không xử lý mục trong trình đơn, hãy gọi phương thức triển khai lớp cấp cao
onOptionsItemSelected()
. Phương thức triển khai mặc định trả về kết quả
false.
Nếu hoạt động của bạn bao gồm các mảnh, thì trước tiên, hệ thống sẽ gọi
onOptionsItemSelected()
cho hoạt động, sau đó cho mỗi mảnh
theo thứ tự thêm các mảnh, cho đến khi một giá trị trả về true
hoặc
tất cả các mảnh đều được gọi.
Thay đổi các mục trong trình đơn trong thời gian chạy
Sau khi gọi onCreateOptionsMenu()
, hệ thống sẽ giữ lại
thực thể của Menu
mà bạn điền và không gọi
onCreateOptionsMenu()
một lần nữa trừ phi trình đơn không hợp lệ.
Tuy nhiên, chỉ sử dụng onCreateOptionsMenu()
để tạo trình đơn ban đầu
trạng thái và không được thực hiện thay đổi trong vòng đời hoạt động.
Nếu bạn muốn sửa đổi trình đơn tuỳ chọn dựa trên các sự kiện xảy ra trong
vòng đời hoạt động, bạn có thể thực hiện việc này trong
onPrepareOptionsMenu()
. Phương thức này truyền cho bạn đối tượng Menu
vì đối tượng này hiện tại
tồn tại để bạn có thể sửa đổi, chẳng hạn như bằng cách thêm, xoá hoặc vô hiệu hoá các mục.
Các mảnh cũng cung cấp
onPrepareOptionsMenu()
.
Trình đơn tuỳ chọn được coi là luôn mở khi các mục trong trình đơn được trình bày
thanh ứng dụng. Khi một sự kiện xảy ra và bạn muốn cập nhật trình đơn, hãy gọi
invalidateOptionsMenu()
để yêu cầu hệ thống gọi onPrepareOptionsMenu()
.
Tạo trình đơn theo bối cảnh
Trình đơn theo bối cảnh cung cấp các thao tác ảnh hưởng đến một mục hoặc ngữ cảnh cụ thể
trong giao diện người dùng. Bạn có thể cung cấp trình đơn theo bối cảnh cho mọi chế độ xem, nhưng đó là
thường được dùng cho các mục trong
RecylerView
hoặc
các tập hợp khung hiển thị khác mà trong đó người dùng có thể thực hiện thao tác trực tiếp trên mỗi
mục.
Có hai cách cung cấp thao tác theo ngữ cảnh:
- Trong trình đơn ngữ cảnh nổi. Một trình đơn sẽ xuất hiện dưới dạng danh sách nổi các mục trong trình đơn, tương tự như một hộp thoại, khi người dùng thực hiện thao tác chạm và giữ một khung hiển thị khai báo hỗ trợ cho một ngữ cảnh . Người dùng có thể thực hiện thao tác theo ngữ cảnh trên một mục tại một thời điểm.
- Ở chế độ thao tác theo ngữ cảnh. Chế độ này là một hệ thống
việc triển khai
ActionMode
hiển thị thanh thao tác theo ngữ cảnh (CAB) ở đầu màn hình có các mục hành động ảnh hưởng đến(các) mục đã chọn. Khi chế độ này đang hoạt động, người dùng có thể thực hiện hành động trên nhiều mục cùng một lúc, nếu ứng dụng hỗ trợ điều đó.
Lưu ý: Trình đơn theo bối cảnh không hỗ trợ phím tắt mục và biểu tượng mục.
Tạo trình đơn theo bối cảnh nổi
Để cung cấp trình đơn theo bối cảnh nổi, hãy làm như sau:
- Đăng ký
View
mà trình đơn theo bối cảnh được liên kết bằng đang gọiregisterForContextMenu()
và truyền vào đóView
.Nếu hoạt động của bạn sử dụng
RecyclerView
và bạn muốn mỗi để cung cấp cùng một trình đơn theo bối cảnh, hãy đăng ký tất cả các mục cho một ngữ cảnh bằng cách chuyểnRecyclerView
đếnregisterForContextMenu()
- Triển khai
onCreateContextMenu()
trongActivity
hoặcFragment
của bạn.Khi chế độ xem đã đăng ký nhận được thao tác chạm & giữ sự kiện, hệ thống sẽ gọi phương thức
onCreateContextMenu()
của bạn. Đây là nơi bạn xác định các mục trong trình đơn, thường bằng cách tăng cường một tài nguyên trình đơn, như sau ví dụ: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
cho phép bạn tăng cường trình đơn ngữ cảnh từ một tài nguyên trình đơn. Phương thức gọi lại các tham số bao gồmView
mà người dùng chọn vàContextMenu.ContextMenuInfo
cung cấp thông tin bổ sung về mục đã chọn. Nếu hoạt động của bạn có nhiều chế độ xem, trong đó mỗi chế độ xem cung cấp một trình đơn theo bối cảnh riêng. bạn có thể sử dụng các thông số này để xác định xem nên sử dụng trình đơn theo bối cảnh nào tăng cường. Triển khai
onContextItemSelected()
, như trong ví dụ sau. Khi người dùng chọn một mục trong trình đơn, hệ thống sẽ gọi phương thức này để bạn có thể thực hiện hành động thích hợp.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()
truy vấn mã nhận dạng cho mục trong trình đơn đã chọn mà bạn chỉ định cho mỗi mục mục trong trình đơn trong XML sử dụng thuộc tínhandroid:id
, như minh hoạ trong Xác định trình đơn trong XML.Khi xử lý thành công một mục trong trình đơn, hãy trả lại
true
. Nếu bạn không xử lý mục trong trình đơn, hãy chuyển mục trong trình đơn đến lớp cấp cao trong quá trình triển khai. Nếu hoạt động có chứa mảnh, thì hoạt động sẽ nhận được lệnh gọi lại này trước tiên. Bằng cách gọi lớp cấp cao khi không được xử lý, hệ thống truyền sự kiện đến phương thức gọi lại tương ứng trong mỗi mảnh, một phương thức tại một lần, theo thứ tự mỗi mảnh được thêm vào, cho đếntrue
hoặc Trả vềfalse
. Các cách triển khai mặc định choActivity
vàandroid.app.Fragment
trả bóngfalse
, vì vậy, hãy luôn gọi lớp cấp cao khi chưa xử lý.
Sử dụng chế độ thao tác theo ngữ cảnh
Chế độ thao tác theo ngữ cảnh là cách triển khai hệ thống của
ActionMode
tập trung sự tương tác của người dùng để đạt được hiệu suất
hành động theo ngữ cảnh. Khi người dùng bật chế độ này bằng cách chọn một mục,
thanh thao tác theo ngữ cảnh xuất hiện ở đầu màn hình để trình bày
hành động mà người dùng có thể thực hiện trên các mục đã chọn. Khi chế độ này bật,
người dùng có thể chọn nhiều mục (nếu ứng dụng của bạn hỗ trợ việc đó) và có thể bỏ chọn
các mục và tiếp tục di chuyển trong hoạt động đó. Chế độ hành động bị tắt
và thanh thao tác theo ngữ cảnh sẽ biến mất khi người dùng bỏ chọn tất cả các mục,
nhấn vào nút Quay lại hoặc nhấn vào thao tác Done (Xong) ở bên trái của
thanh.
Đối với những khung hiển thị cung cấp thao tác theo ngữ cảnh, bạn thường gọi thuộc tính ngữ cảnh chế độ hành động khi một hoặc cả hai sự kiện sau xảy ra:
- Người dùng thực hiện thao tác chạm và giữ nguyên khung hiển thị.
- Người dùng chọn hộp đánh dấu hoặc thành phần giao diện người dùng tương tự trong chế độ xem.
Cách ứng dụng gọi chế độ thao tác theo ngữ cảnh và xác định cho từng tác vụ tuỳ thuộc vào thiết kế của bạn. Có hai thiết kế:
- Tùy ý đối với các thao tác theo ngữ cảnh trên chế độ xem riêng lẻ.
- Đối với các thao tác theo ngữ cảnh hàng loạt trên các nhóm mục trong một
RecyclerView
, cho phép người dùng chọn nhiều mục và thực hiện hành động đối với tất cả các quảng cáo đó.
Phần sau đây mô tả cách thiết lập bắt buộc cho từng trường hợp.
Bật chế độ thao tác theo ngữ cảnh cho từng chế độ xem
Nếu bạn chỉ muốn gọi chế độ thao tác theo ngữ cảnh khi người dùng chọn chế độ xem cụ thể, hãy làm như sau:
- Triển khai giao diện
ActionMode.Callback
như minh hoạ trong ví dụ sau. Trong phương thức gọi lại, bạn có thể chỉ định thao tác cho thanh thao tác theo ngữ cảnh, phản hồi các sự kiện nhấp chuột vào các mục hành động và xử lý các sự kiện khác trong vòng đời cho chế độ thao tác.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; } };
Những lệnh gọi lại sự kiện này gần như giống hệt với lệnh gọi lại cho trình đơn tùy chọn, ngoại trừ mỗi trình đơn này cũng truyền đối tượng
ActionMode
liên kết với sự kiện. Bạn có thể sử dụng các APIActionMode
để thực hiện nhiều thay đổi đối với CAB, chẳng hạn như sửa đổi tiêu đề và phụ đề bằngsetTitle()
vàsetSubtitle()
, chỉ số này rất hữu ích khi cho biết số lượng mục được chọn.Mẫu ở trên đặt biến
actionMode
thànhnull
khi huỷ chế độ hành động. Trong bước tiếp theo, hãy xem cách khởi động biến đó và cách lưu biến thành viên trong hoạt động hoặc có thể hữu ích. - Gọi điện
startActionMode()
khi bạn muốn hiển thị thanh này, chẳng hạn như khi người dùng thực hiện thao tác chạm và giữ nguyên khung hiển thị.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; } });
Khi bạn gọi
startActionMode()
, hệ thống sẽ trả về Đã tạoActionMode
. Khi lưu dữ liệu này trong biến thành viên, bạn có thể thực hiện thay đổi đối với thanh thao tác theo ngữ cảnh để phản hồi các sự kiện khác. Trong mẫu trước,ActionMode
được dùng để đảm bảo rằng thực thểActionMode
sẽ không được tạo lại nếu đã tồn tại đang hoạt động, bằng cách kiểm tra xem thành phần có giá trị rỗng hay không trước khi bắt đầu thao tác .
Tạo trình đơn bật lên
Một PopupMenu
là một trình đơn cửa sổ phụ được liên kết với View
. Quảng cáo này xuất hiện bên dưới quảng cáo cố định
xem có còn chỗ hay không hoặc ở phía trên chế độ xem. Công cụ này hữu ích cho
sau:
- Cung cấp trình đơn kiểu mục bổ sung cho các thao tác liên quan đến nội dung cụ thể, chẳng hạn như tiêu đề email của Gmail, được hiển thị trong hình 4.
- Cung cấp phần thứ hai của một câu lệnh, chẳng hạn như nút được đánh dấu Add (Thêm) để tạo trình đơn bật lên với các tuỳ chọn Add (Thêm) .
- Cung cấp thực đơn tương tự như
Spinner
không giữ lại lựa chọn liên tục.
Nếu xác định trình đơn trong XML, dưới đây là cách bạn có thể hiển thị trình đơn bật lên:
- Tạo thực thể cho
PopupMenu
bằng hàm khởi tạo. Việc này sẽ lấy ứng dụng hiện tạiContext
vàView
mà trình đơn được liên kết. - Sử dụng
MenuInflater
để tăng cường tài nguyên trình đơn của bạn vào Đối tượngMenu
được trả về bởiPopupMenu.getMenu()
. - Gọi
PopupMenu.show()
.
Ví dụ: đây là nút hiển thị trình đơn bật lên:
<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" />
Sau đó, tác vụ có thể hiển thị trình đơn bật lên như sau:
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(); });
Trình đơn sẽ đóng khi người dùng chọn một mục hoặc nhấn vào bên ngoài trình đơn
. Bạn có thể theo dõi sự kiện loại bỏ bằng cách sử dụng
PopupMenu.OnDismissListener
.
Xử lý các sự kiện nhấp chuột
Để thực hiện một thao tác khi người dùng chọn một mục trong trình đơn, hãy triển khai
PopupMenu.OnMenuItemClickListener
giao diện và đăng ký nó với PopupMenu
bằng cách gọi
setOnMenuItemclickListener()
.
Khi người dùng chọn một mục, hệ thống sẽ gọi
onMenuItemClick()
trong giao diện.
Lệnh này được minh hoạ trong ví dụ sau:
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; } }
Tạo một nhóm thực đơn
Nhóm trình đơn là một tập hợp các mục trong trình đơn có chung đặc điểm nhất định. Có nhóm, bạn có thể làm như sau:
- Hiển thị hoặc ẩn tất cả các mục bằng
setGroupVisible()
. - Bật hoặc tắt tất cả các mục bằng
setGroupEnabled()
. - Chỉ định xem có thể đánh dấu tất cả các mục hay không bằng
setGroupCheckable()
.
Bạn có thể tạo một nhóm bằng cách lồng các phần tử <item>
bên trong
phần tử <group>
trong tài nguyên trình đơn của bạn hoặc bằng cách chỉ định một
mã nhóm có
add()
.
Dưới đây là ví dụ về tài nguyên trình đơn bao gồm một nhóm:
<?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>
Các mục trong nhóm này sẽ xuất hiện ở cùng cấp với mục đầu tiên
mục – cả 3 mục trong trình đơn đều đồng cấp. Tuy nhiên, bạn có thể sửa đổi
đặc điểm của hai mục trong nhóm bằng cách tham chiếu mã nhóm và sử dụng
các phương thức trước đó. Hệ thống cũng không bao giờ tách riêng các mục đã được nhóm với nhau. Cho
Ví dụ: nếu bạn khai báo android:showAsAction="ifRoom"
cho mỗi
mục, cả hai đều xuất hiện trong thanh tác vụ hoặc cả hai đều xuất hiện trong hành động
tràn.
Sử dụng các mục trong trình đơn có thể đánh dấu
Trình đơn có thể hữu ích như một giao diện để bật và tắt các tuỳ chọn, sử dụng hộp đánh dấu cho các tuỳ chọn độc lập, hoặc nút chọn cho các nhóm các lựa chọn độc quyền. Hình 5 cho thấy một trình đơn con gồm các mục có thể đánh dấu nút chọn.
Bạn có thể xác định hành vi có thể đánh dấu cho từng mục trong trình đơn bằng cách sử dụng
Thuộc tính android:checkable
trong <item>
hoặc cho toàn bộ nhóm có android:checkableBehavior
trong phần tử <group>
. Ví dụ: tất cả các mục trong
nhóm trình đơn này có thể đánh dấu bằng nút chọn:
<?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>
Thuộc tính android:checkableBehavior
chấp nhận một trong
sau:
single
- Chỉ có thể đánh dấu một mục trong nhóm, dẫn đến radio các nút.
all
- Tất cả các mục đều có thể đánh dấu vào hộp, dẫn đến việc có hộp đánh dấu.
none
- Không có mục nào đánh dấu được.
Bạn có thể áp dụng trạng thái đã đánh dấu mặc định cho một mục bằng cách sử dụng
Thuộc tính android:checked
trong phần tử <item>
và thay đổi mã trong mã bằng
setChecked()
.
Khi bạn chọn một mục có thể đánh dấu, hệ thống sẽ gọi các mục tương ứng
phương thức gọi lại do mục chọn, chẳng hạn như onOptionsItemSelected()
.
Đây là nơi bạn đặt trạng thái của hộp đánh dấu, vì hộp đánh dấu hoặc nút
nút sẽ không tự động thay đổi trạng thái. Bạn có thể truy vấn trạng thái hiện tại
của mặt hàng—như trước khi người dùng chọn mặt hàng—với
isChecked()
rồi đặt trạng thái đã đánh dấu bằng setChecked()
. Nội dung này được thể hiện trong
ví dụ sau:
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); } }
Nếu bạn không đặt trạng thái đã đánh dấu theo cách này, thì trạng thái hiển thị của hộp đánh dấu hoặc nút chọn không thay đổi khi người dùng chọn hộp đánh dấu đó. Khi bạn thực hiện thiết lập trạng thái, hoạt động sẽ duy trì trạng thái đã đánh dấu của mục để khi người dùng mở trình đơn vào lúc khác, trạng thái đã đánh dấu mà bạn đặt là hiển thị.
Thêm các mục trong trình đơn dựa trên ý định
Đôi khi, bạn muốn một mục trong trình đơn khởi chạy một hoạt động bằng một
Intent
,
cho dù đó là hoạt động trong ứng dụng của bạn hay một ứng dụng khác. Khi
biết ý định bạn muốn sử dụng và có một mục cụ thể trong trình đơn bắt đầu
ý định, bạn có thể thực thi ý định bằng
startActivity()
trong phương thức gọi lại thích hợp theo mục đã chọn, chẳng hạn như
Gọi lại onOptionsItemSelected()
.
Tuy nhiên, nếu bạn không chắc chắn rằng thiết bị của người dùng có chứa một ứng dụng xử lý ý định, thì việc thêm một mục trong trình đơn gọi ra mục đó có thể dẫn đến mục trong trình đơn không hoạt động vì ý định có thể không phân giải thành một hoạt động. Để giải quyết vấn đề này, Android cho phép bạn tự động thêm các mục trong trình đơn khi Android tìm các hoạt động trên thiết bị xử lý ý định của bạn.
Để thêm các mục trong trình đơn dựa trên các hoạt động có sẵn chấp nhận một ý định, hãy làm như sau như sau:
- Xác định một ý định bằng danh mục
CATEGORY_ALTERNATIVE
hoặcCATEGORY_SELECTED_ALTERNATIVE
, hoặc cả hai và mọi yêu cầu khác. - Gọi điện
Menu.addIntentOptions()
. Sau đó, Android sẽ tìm kiếm bất kỳ ứng dụng nào có thể thực hiện ý định và thêm chúng vào trình đơn của bạn.
Nếu không có ứng dụng nào được cài đặt đáp ứng ý định, thì sẽ không có trình đơn nào mục đã được thêm.
Lệnh này được minh hoạ trong ví dụ sau:
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; }
Đối với mỗi hoạt động được tìm thấy cung cấp một bộ lọc ý định khớp với ý định
đã xác định, một mục trong trình đơn sẽ được thêm vào bằng cách sử dụng giá trị trong
android:label
là tiêu đề mục trong trình đơn và biểu tượng ứng dụng làm trình đơn
biểu tượng mục. Phương thức addIntentOptions()
trả về số lượng
đã thêm mục trong trình đơn.
Cho phép thêm hoạt động của bạn vào các trình đơn khác
Bạn có thể cung cấp dịch vụ liên quan đến hoạt động của mình cho các ứng dụng khác để ứng dụng đó có thể được bao gồm trong trình đơn của các mục khác—thu hồi các vai trò được mô tả trước đó.
Để được đưa vào các trình đơn khác của ứng dụng, hãy xác định bộ lọc ý định như bình thường,
nhưng bao gồm CATEGORY_ALTERNATIVE
hoặc
Giá trị CATEGORY_SELECTED_ALTERNATIVE
hoặc cả hai cho ý định
danh mục bộ lọc. Lệnh này được minh hoạ trong ví dụ sau:
<intent-filter label="@string/resize_image"> ... <category android:name="android.intent.category.ALTERNATIVE" /> <category android:name="android.intent.category.SELECTED_ALTERNATIVE" /> ... </intent-filter>
Đọc thêm về cách viết bộ lọc ý định trong Ý định và ý định .