讓 UIPickerView 取代鍵盤吧 — 利用 inputView & inputAccessoryView
開發 iOS App 時,我們時常從 Picker View 輸入選擇的項目。而 Picker View 出現的方式有許多種,其中一種常見的設計是像鍵盤一樣由下而上出現,例如下圖高鐵 App 的地點選擇。
這樣的功能其實不難實現,比方我們可利用隱藏的 text filed,inputView & inputAccessoryView。
接下來我們將以選擇好聽的黑色歌曲為例,示範如何實現取代鍵盤的 UIPickerView,讓它像鍵盤一樣由下而上出現,並在 picker view 的上方加上一條搭配 button 的 bar,方便使用者確定和取消選取。
從 storyboard 設計畫面
- 加入 label & tap gesture recognizer
我們希望點選 label 後出現 picker view,因此加入 label 後,請勾選 label 的 User Interaction Enabled,然後將 tap gesture recognizer 加到 label 上。
- 加入 picker view
將 picker view 加到 Exit 下,讓它出現在畫面之外,因為 picker view 將在 label 點選時才出現。
將 controller 設為 picker view 的 data source & delegate。
- 加入 Toolbar & Bar Button Item
將 Toolbar 加到 Exit 下,讓它出現在畫面之外,因為 ToolBar 將在 label 點選時才出現在 picker view 的上方。在 Toolbar 加入 Cancel & Done 的 Bar Button Item,中間則加入 Flexible Space Bar Button Item。
- 加入隱藏的 text field
在畫面上加入 text field,將它設為 hidden。隱藏的 text field 雖然看不到,但是卻責任重大,它將讓 picker view 取代鍵盤,讓 picker view 像鍵盤一樣由下而上出現。
連結 outlet & action
tap gesture recognizer 連到 selectSong,done button 連到 selectSongDone,cancel button 連到 selectSongCancel。
class ViewController: UIViewController {
@IBOutlet weak var songTextField: UITextField!
@IBOutlet weak var songLabel: UILabel!
@IBOutlet var songToolbar: UIToolbar!
@IBOutlet var songPickerView: UIPickerView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
@IBAction func selectSong(_ sender: Any) {
}
@IBAction func selectSongCancel(_ sender: Any) {
}
@IBAction func selectSongDone(_ sender: Any) {
}
}
設定 picker view 顯示的內容
在 controller 裡加入 array songs,儲存四首好聽的黑色歌曲。
class ViewController: UIViewController {
let songs = ["黑色毛衣", "黑色幽默", "黑色小狗", "黑色柳丁"]
定義 UIPickerViewDataSource & UIPickerViewDelegate 的相關 function,顯示 array songs 的內容。
extension ViewController: UIPickerViewDataSource, UIPickerViewDelegate {
func numberOfComponents(in pickerView: UIPickerView) -> Int {
1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
songs.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
songs[row]
}
}
設定 text field 的輸入區塊為 picker view,picker view 上方顯示 toolbar
inputView
是 text filed 輸入時從下方冒出的輸入區塊,它預設是內建的鍵盤,我們將它換成 picker view。inputAccessoryView
是輸入區塊上方的輔助區塊,我們將它換成 toolbar,因此 toolbar 將長在 picker view 上方。
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
songTextField.inputView = songPickerView
songTextField.inputAccessoryView = songToolbar
}
點選 label 時顯示 picker view
點選 label 會呼叫 selectSong,我們從 text filed 呼叫 becomeFirstResponder,觸發 text filed 的輸入區塊出現。由於 inputView 已被我們換成 picker view,因此會變成 picker view 出現。
@IBAction func selectSong(_ sender: Any) {
songTextField.becomeFirstResponder()
}
點擊 toolbar 的 button 關閉 picker view,在 label 上顯示選取的歌曲
@IBAction func selectSongCancel(_ sender: Any) {
view.endEditing(true)
}
@IBAction func selectSongDone(_ sender: Any) {
let row = songPickerView.selectedRow(inComponent: 0)
songLabel.text = songs[row]
view.endEditing(true)
}
執行 App
點擊 label 後 picker 真的出現了 ! 彼得潘因為穿著黑色毛衣,因此選擇它,然後點選 Done,讓 label 上的文字變成黑色毛衣。