讓 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 上的文字變成黑色毛衣。

範例連結

--

--

彼得潘的 iOS App Neverland
彼得潘的 Swift iOS App 開發問題解答集

彼得潘的iOS App程式設計入門,文組生的iOS App程式設計入門講師,彼得潘的 Swift 程式設計入門,App程式設計入門作者,http://apppeterpan.strikingly.com