iOS 的選單(menu)按鈕 — Pull Down Button & Pop Up Button
從 iOS 14 開始,我們可以更方便地製作選單按鈕,呈現類似下拉式選單的效果。
接下來我們將介紹兩種選單(menu)按鈕的實現方法。
- Pull Down Button
點選按紐後將顯示選單,列出使用者可選擇的選項。
- Pop Up Button
按鈕的標題顯示選單裡被選到的選項,被選到的選項將打勾(單選)。
點選後顯示選單的 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 參數加入圖片。
- 顯示 SF Symbol 的圖片。
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")
})
])
- 顯示 Assets 的彩色圖片。
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 有不同的做法。
- iOS 15
產生 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")
})
])
- iOS 14
我們必須自己記錄被選到的項目,然後在 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 的做法。
- iOS 15
除了設定 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("味全龍隊")
})
])
}
}
如下圖所示,按鈕的標題隨著我們點選的選項更新。
- iOS 14
我們必須自己寫程式實現 Pop Up Button 的功能,在點選選項時更新按鈕的標題。
將 menu 加到 UIBarButtonItem
剛剛的例子我們都是將 menu 加到 UIButton 上,其實它也可以加到 UIBarButtonItem。
- Pull Down Button
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 才會顯示。
- Pop Up Button
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
}
}
設定 Pop Up Button / Pull Down Button 下 command 的 selector
開發 iOS App 時,我們可以在 Interface Builder 加入方便顯示選單的 Pop Up Button & Pull Down Button。不過事情沒有想像中簡單,想讓它們發揮作用還得做些調整。
參考連結
Human Interface Guidelines 的 button 介紹。
Apple 官方範例 UIKit Catalog: Creating and Customizing Views and Controls。