iOS 的選單(menu)按鈕 — Pull Down Button & Pop Up Button 從 iOS 14 開始,我們可以更方便地製作選單按鈕,呈現類似下拉式選單的效果。
接下來我們將介紹兩種選單(menu)按鈕的實現方法。
點選按紐後將顯示選單,列出使用者可選擇的選項。
按鈕的標題顯示選單裡被選到的選項,被選到的選項將打勾(單選)。
點選後顯示選單的 Pull Down Button 將 UIButton 的 showsMenuAsPrimaryAction 設為 true,利用 UIMenu 製作選單,每個選項由 UIAction 產生。由於 UIButton 在 iOS 14 才有 property showsMenuAsPrimaryAction & menu,因此以下程式只支援 iOS 14 以上的版本。
class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. let button = UIButton(type: .system) button.frame = CGRect(x: 100, y: 100, width: 100, height: 100) button.setTitle("Edit", for: .normal) view.addSubview(button) button.showsMenuAsPrimaryAction = true button.menu = UIMenu(children: [ UIAction(title: "Select Messages", handler: { action in print("Select Messages") }), UIAction(title: "Edit Pins", handler: { action in print("Edit Pins") }), UIAction(title: "Edit Name and Photo", handler: { action in print("Edit Name and Photo") }) ]) } } 點選 button 後將顯示選單,點選某個選項或是空白處都可關閉選單。
menu 出現的位置跟順序 依據 button 在畫面上的位置,menu 出現的位置跟順序也會有所不同。
當 button 比較靠上面,點選 button 時選單將出現在 button 下方,選項的順序則跟 UIAction array 的順序一致。 當 button 比較靠下面,點選 button 時選單將出現在 button 上方,選項的順序則跟 UIAction array 的順序相反。 包含圖片跟文字的 menu menu 的選單除了文字,也可以透過 UIAction 的 image 參數加入圖片。
button.showsMenuAsPrimaryAction = true button.menu = UIMenu(children: [ UIAction(title: "Select Messages", image: UIImage(systemName: "checkmark.circle") , handler: { action in print("Select Messages") }), UIAction(title: "Edit Pins", image: UIImage(systemName: "pin"), handler: { action in print("Edit Pins") }), UIAction(title: "Edit Name and Photo", image: UIImage(systemName: "person.crop.circle"), handler: { action in print("Edit Name and Photo") }) ]) asset 的圖片將自動縮小,不需要另外調整。
button.showsMenuAsPrimaryAction = true button.menu = UIMenu(children: [ UIAction(title: "Select Messages", image: UIImage(named: "peter") , handler: { action in print("Select Messages") }), UIAction(title: "Edit Pins", image: UIImage(systemName: "pin"), handler: { action in print("Edit Pins") }), UIAction(title: "Edit Name and Photo", image: UIImage(systemName: "person.crop.circle"), handler: { action in print("Edit Name and Photo") }) ]) menu 裡有 menu 如果選項很多,我們也可以在 menu 裡再加入另一層 menu。以下例子裡參數 children array 的前兩個是 UIAction,第三個是第二層的 menu。
button.showsMenuAsPrimaryAction = true button.menu = UIMenu(children: [ UIAction(title: "Select Messages", image: UIImage(systemName: "checkmark.circle"), handler: { action in print("Select Messages") }), UIAction(title: "Edit Pins", image: UIImage(systemName: "pin"), handler: { action in print("Edit Pins") }), UIMenu(title: "Sort By", image: UIImage(systemName: "arrow.up.arrow.down"), children: [ UIAction(title: "Manual", handler: { action in print("Manual") }), UIAction(title: "Due Date", handler: { action in print("Due Date") }) ]) ]) 點選 Sort By 後將顯示第二層的 menu。
將 menu 裡選到的選項打勾 產生 UIAction 時,參數 state 傳入 .on 可讓選項打勾。若是想實現只有一個選項能打勾的單選效果,在 iOS 15 跟 14 有不同的做法。
產生 UIMenu 時在參數 options 傳入 .singleSelection,它會自己記得目前被選到的項目,然後將選到的項目打勾。
button.showsMenuAsPrimaryAction = true button.menu = UIMenu(options: .singleSelection , children: [ UIAction(title: "Manual", state: .on , handler: { action in print("Manual") }), UIAction(title: "Due Date", handler: { action in print("Due Date") }) ]) 我們必須自己記錄被選到的項目,然後在 UIAction 裡設定要打勾的選項。
利用分隔線將 menu 分組 當選項很多時,我們可以利用 separator 將 menu 分組,讓使用者知道某些選項是相關的項目。分組的方法是在 menu 裡加入 menu,然後讓第一層的 menu 選項跟第二層的 menu 選項同時顯示並用分隔線隔開,如此即可呈現下圖的 menu 分組效果。
以下程式產生第二層 menu 時參數 options 傳入 .displayInline,它將讓第一層的 menu 選項跟第二層的 menu 選項同時顯示並用分隔線隔開。
button.showsMenuAsPrimaryAction = true button.menu = UIMenu(children: [ UIAction(title: "Select", handler: { action in print("Select") }), UIAction(title: "New Folder", handler: { action in print("New Folder") }), UIAction(title: "Scan Documents", handler: { action in print("Scan Documents") }), UIAction(title: "Connect to Server", handler: { action in print("Connect to Server") }), UIMenu(options: .displayInline , children: [ UIAction(title: "Icons", handler: { action in print("Icons") }), UIAction(title: "List", handler: { action in print("List") }) ]) ]) Pop Up Button 除了點選後會顯示選單,Pop Up Button 多了以下功能:
按鈕的標題將顯示選單裡被選到的選項。 只能單選,被選到的選項將打勾。 自動記得目前被選到的項目。 以下分別介紹 iOS 15 跟 14 的做法。
除了設定 button 的 showsMenuAsPrimaryAction & menu,還要將 changesSelectionAsPrimaryAction 設為 true。changesSelectionAsPrimaryAction 是 iOS 15 才有的 property,因此只支援 15 以上的版本。
class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. let button = UIButton(type: .system) button.frame = CGRect(x: 100, y: 100, width: 200, height: 100) view.addSubview(button) button.showsMenuAsPrimaryAction = true button.changesSelectionAsPrimaryAction = true button.menu = UIMenu(children: [ UIAction(title: "統一7-ELEVEn獅隊", state: .on, handler: { action in print("統一7-ELEVEn獅隊") }), UIAction(title: "中信兄弟隊", handler: { action in print("中信兄弟隊") }), UIAction(title: "樂天桃猿隊", handler: { action in print("樂天桃猿隊") }), UIAction(title: "富邦悍將隊", handler: { action in print("富邦悍將隊") }), UIAction(title: "味全龍隊", handler: { action in print("味全龍隊") }) ]) } } 如下圖所示,按鈕的標題隨著我們點選的選項更新。
我們必須自己寫程式實現 Pop Up Button 的功能,在點選選項時更新按鈕的標題。
將 menu 加到 UIBarButtonItem 剛剛的例子我們都是將 menu 加到 UIButton 上,其實它也可以加到 UIBarButtonItem。
class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. let menu = UIMenu(children: [ UIAction(title: "Select Messages", handler: { action in print("Select Messages") }), UIAction(title: "Edit Pins", handler: { action in print("Edit Pins") }), UIAction(title: "Edit Name and Photo", handler: { action in print("Edit Name and Photo") }) ]) navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Edit", menu: menu) } } 記得要搭配 navigation controller,navigationItem 設定的 rightBarButtonItem 才會顯示。
class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. let menu = UIMenu(children: [ UIAction(title: "統一7-ELEVEn獅隊", state: .on, handler: { action in print("統一7-ELEVEn獅隊") }), UIAction(title: "中信兄弟隊", handler: { action in print("中信兄弟隊") }), UIAction(title: "樂天桃猿隊", handler: { action in print("樂天桃猿隊") }), UIAction(title: "富邦悍將隊", handler: { action in print("富邦悍將隊") }), UIAction(title: "味全龍隊", handler: { action in print("味全龍隊") }) ]) let barButtonItem = UIBarButtonItem(menu: menu) barButtonItem.changesSelectionAsPrimaryAction = true navigationItem.rightBarButtonItem = barButtonItem } } 參考連結 Human Interface Guidelines 的 button 介紹。
Apple 官方範例 UIKit Catalog: Creating and Customizing Views and Controls