Xcode-Popover and Check Mark Practice
目錄
⦿ Popover and Check Mark
⦿ Storyboard
⦿ TableViewController
Popover and Check Mark
在之前的文章,我們知道如果使用 UIAlertController 時,可以選擇 .alert
或 .actionSheet
來彈出提示框,.alert
是一般常見從中間彈出的提示框,.actionSheet
則是從底部彈出的提示框。
我們稱 alert 這種提示框為 Popup。
.alert
的應用場景為提示、警示、創建帳號、輸入密碼等,若要客製化另一種提示框就不是使用 UIAlertController 了,先看到如下:
在 Navigation Bar 的 rightBarButtonItem,我們看到的是一張系統圖
為 plus.square.fill.on.square.fill
,是一個加號,若按下 rightBarButton,會彈出另一個提示框,提示框叫做 Popover,提示框的項目中,有兩項已經打勾(Check Mark)。
點選提示框各項,若要能夠打勾
與取消打勾
,應該怎麼做呢?
用 popoverPresentationController,是的!這種依附在別的元件上的提示框就稱為 Popover
。
接下來,一步步教大家如何使用 Popover 吧!
繼續閱讀|回目錄
Storyboard
在 Storyboard 中,我們先將 VC 嵌入 Navigation Controller,在 Right Bar Button Items 選擇一個圖片如下圖左:
看到右圖,再從這個 Bar Button 寫一個 IBAction,程式碼列出如下:
@IBAction func rightBarButtonItemTapped(_ sender: UIBarButtonItem) {
let vc = PopoverPresentationTableViewController()
// 設定為提示框形式
vc.modalPresentationStyle = .popover
// 指定提示框的彈出位置為 rightBarButtonItem
vc.popoverPresentationController?.barButtonItem = navigationItem.rightBarButtonItem
// 設定 delegate
vc.popoverPresentationController?.delegate = self
vc.preferredContentSize = CGSize(width: 200, height: 177)
present(vc, animated: true, completion: nil)
}
當按下 button 後,會產生一個 VC,這邊是 PopoverPresentationTableViewController
,由於我們還沒加入這個 TableViewController,所以先看到後面的程式碼。
VC 是你的提示框,提示框的形式為 popover,VC 往上找到管理它的 Controller,這個 Controller 的 barButtonItem 將之設為 navigationItem.rightBarButtonItem
,意思即是當 VC 彈出來時,會以 rightBarButton 做定位,或說由 rightBarButton 彈出 VC
。
接著設定 UIPopoverPresentationControllerDelegate
的 delegate
,所以在 VC 還需遵循 UIPopoverPresentationControllerDelegate 這個 protocol。
最後設定 VC 做為提示框時的 Content Size
,再 present 出來。
但是!假定你已經創建了這個 VC 的 class,此時按下 rightBarButton 仍然不會是我們要的提示框形式,會出現如下:
竟然呈現便利貼
的形式,我們必須還要在 VC 中加入一段程式碼如下:
func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
return .none
}
這段程式碼大致是說不要因為環境而去改變 VC 的 PresentationStyle,如此才能得到我們想要的結果。
繼續閱讀|回目錄
TableViewController
如果要做 Popover,通常建議是使用 TableViewController,像是在 Storyboard 中加入 Static Cell,再設定 Cell 的數量及內容。
由於前段是以 PopoverPresentationTableViewController()
去創建 VC,所以接下來是程式碼的編寫,首先要注意的是 Check Mark,點擊 Cell Row 沒有問題,我們可用 indexPath
去記錄點了哪一個 Section
的哪一個 Row
,若只有一個 Section,indexPath.row 就是你點擊的項目編號。
我們先宣告幾個 Properties 如下:
private var items = ["天干", "地支", "生年", "大運"]
private var selectedItems = Set<Int>()
private let identifier = "checklistCell"
items
就是 Popover 的內容;selectedItems
是一個 Int 型別的 Set,概念是點擊的 Cell Row(即項目編號),把這個編號存起來,再次點擊就把該項目編號移除;由於是程式碼產生 Cell,便在此給予 identifier
。
所以,我們先看 didSelectRowAt
的編寫:
override func tableView(_ tableView: UITableView,
didSelectRowAt indexPath: IndexPath) {
// 若點擊的位置在該 indexPathRow
if let cell = tableView.cellForRow(at: indexPath) {
// 改變 checkmark 狀態
if cell.accessoryType == .checkmark {
cell.accessoryType = .none
// 記錄 checkmark 狀態
selectedItems.remove(indexPath.row)
} else {
cell.accessoryType = .checkmark
selectedItems.insert(indexPath.row)
}
// 選取 cellRow 反白會消失
tableView.deselectRow(at: indexPath, animated: true)
}
}
tableView.cellForRow 是從 indexPath 去找到 Cell 的 Row,再改變此 Row 的 accessoryType,即在 .none
與 .checkmark
間切換,如果是 checkmark 狀態切換成 none,selectedItems 就要移除該 indexPath.row
(項目編號);反之,則要加入該 indexPath.row
。
最後 deselectRow
,因為預設點擊 TableViewCell 的反應是變灰色,這預設會讓點擊看起來很醜,所以要讓它再從灰色變回白色。
接著是 data source 的部分如下:
override func tableView(_ tableView: UITableView,
numberOfRowsInSection section: Int) -> Int {
return items.count
}
override func tableView(_ tableView: UITableView,
cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: identifier,
for: indexPath)
cell.textLabel?.text = items[indexPath.row]
// 確認 cellRow 是否有 checkmark
if selectedItems.contains(indexPath.row) {
cell.accessoryType = .checkmark
} else {
cell.accessoryType = .none
}
return cell
}
items.count 即是 Cell Row 的數量;而 dequeReusableCell
必須在 identifier 註冊過的情況下,我們使用預設的 Cell 的形式,去設定它的 textLabel?.text
的項目顯示;最後則是以 selectedItems 去檢查項目編號是否被存進去了,存進去表示有 checkmark,沒存進去,cell 的 accessoryType 則是 .none
。
最後記得 viewDidLoad()
中:
self.tableView.register(UITableViewCell.self,
forCellReuseIdentifier: identifier)
把自己的 Cell 註冊一個 ID 來 reusable。
完成了!
前面的 Popover 是用程式碼生成的,我們也可以用 Storyboard 去生成這個 TableViewController,這時候要記得將 Cell 設為 Static,而 TableView 的 style 設為 Grouped 或 Inset Grouped 會比較好看,但實測結果還是程式碼生成的顏值高一些。