用 UIPickerView 替换键盘

在某些情况下,你希望向用户显示 UIPickerView 其中包含 UITextField 而非键盘的预定义内容。

创建自定义 UIPickerView

首先,你需要一个符合 UIPickerViewDataSourceUIPickerViewDelegate 协议的 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 需要属性 dataselectedValuetextFieldBeingEdited

/**
 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 作为你的 UITextFieldinputView

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,你应该看到这样的选择器而不是键盘:

StackOverflow 文档

以编程方式选择值(可选)

如果你不想自动选择第一行,可以像在 UIPickerView 中一样设置所选行:

picker?.selectRow(3, inComponent: 0, animated: false) //Will select the row at index 3