用 UIPickerView 替换键盘
在某些情况下,你希望向用户显示 UIPickerView
, 其中包含 UITextField
而非键盘的预定义内容。
创建自定义 UIPickerView
首先,你需要一个符合 UIPickerViewDataSource
和 UIPickerViewDelegate
协议的 UIPickerView
自定义包装器类。
class MyPickerView: UIPickerView, UIPickerViewDataSource, UIPickerViewDelegate
你需要为 DataSource 和 Delegate 实现以下方法:
public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if data != nil {
return data!.count
} else {
return 0
}
}
public func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
public func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if data != nil {
return data![row]
} else {
return ""
}
}
要处理数据,MyPickerView
需要属性 data
,selectedValue
和 textFieldBeingEdited
:
/**
The data for the `UIPickerViewDelegate`
Always needs to be an array of `String`! The `UIPickerView` can ONLY display Strings
*/
public var data: [String]? {
didSet {
super.delegate = self
super.dataSource = self
self.reloadAllComponents()
}
}
/**
Stores the UITextField that is being edited at the moment
*/
public var textFieldBeingEdited: UITextField?
/**
Get the selected Value of the picker
*/
public var selectedValue: String {
get {
if data != nil {
return data![selectedRow(inComponent: 0)]
} else {
return ""
}
}
}
准备 ViewController
包含 textField 的 ViewController
需要具有自定义 UIPickerView
的属性。 (假设你已经有另一个属性或包含 textField 的 @IBOutlet
)
/**
The picker view to present as keyboard
*/
var picker: MyPickerView?
在你的 viewDidLoad()
中,你需要初始化 picker
并对其进行一些配置:
picker = MyPickerView()
picker?.autoresizingMask = [.flexibleHeight, .flexibleWidth]
picker?.backgroundColor = UIColor.white()
picker?.data = ["One", "Two", "Three", "Four", "Five"] //The data shown in the picker
现在,你可以添加 MyPicker
作为你的 UITextField
的 inputView
:
textField.inputView = picker
解雇拣货员键盘
现在,你已经用 UIPickerView
替换了键盘,但没有可能将它解雇。这可以通过自定义 .inputAccessoryView
来完成:
将属性 pickerAccessory
添加到你的 ViewController
。
/**
A toolbar to add to the keyboard when the `picker` is presented.
*/
var pickerAccessory: UIToolbar?
在 viewDidLoad()
中,你需要为 inputAccessoryView
创建一个 UIToolbar
:
pickerAccessory = UIToolbar()
pickerAccessory?.autoresizingMask = .flexibleHeight
//this customization is optional
pickerAccessory?.barStyle = .default
pickerAccessory?.barTintColor = UIColor.red()
pickerAccessory?.backgroundColor = UIColor.red()
pickerAccessory?.isTranslucent = false
你应该设置工具栏的框架。为了适应 iOS 的设计,建议使用 44.0
的高度:
var frame = pickerAccessory?.frame
frame?.size.height = 44.0
pickerAccessory?.frame = frame!
为了获得良好的用户体验,你应该添加两个按钮(完成和取消),但它也只能用于解除键盘的一个按钮。
let cancelButton = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(ViewController.cancelBtnClicked(_:)))
cancelButton.tintColor = UIColor.white()
let flexSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) //a flexible space between the two buttons
let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(ViewController.doneBtnClicked(_:)))
doneButton.tintColor = UIColor.white()
//Add the items to the toolbar
pickerAccessory?.items = [cancelButton, flexSpace, doneButton]
现在你可以将工具栏添加为 inputAccessoryView
textField.inputAccessoryView = pickerAccessory
在构建项目之前,需要实现方法,按钮正在调用:
/**
Called when the cancel button of the `pickerAccessory` was clicked. Dismsses the picker
*/
func cancelBtnClicked(_ button: UIBarButtonItem?) {
textField?.resignFirstResponder()
}
/**
Called when the done button of the `pickerAccessory` was clicked. Dismisses the picker and puts the selected value into the textField
*/
func doneBtnClicked(_ button: UIBarButtonItem?) {
textField?.resignFirstResponder()
textField.text = picker?.selectedValue
}
运行你的项目,点击 textField
,你应该看到这样的选择器而不是键盘:
以编程方式选择值(可选)
如果你不想自动选择第一行,可以像在 UIPickerView
中一样设置所选行:
picker?.selectRow(3, inComponent: 0, animated: false) //Will select the row at index 3