阻止编辑 UITextField 但不阻止 Swift 中的用户交互
Prevent editing UITextField but not the user interaction in Swift
我想知道如何阻止用户编辑 UITextField 而不是用户交互。我想在这里做的是当用户点击文本字段时,UIPickerView 从底部弹出,用户可以 select 选择器视图中的项目并将其显示在文本字段上。但我不希望用户能够编辑文本字段。我想为下面的 class 执行此操作。
import UIKit
typealias PickerTextFieldDisplayNameHandler = ((Any) -> String)
typealias PickerTextFieldItemSelectionHandler = ((Int, Any) -> Void)
class PickerTextField: UITextField {
private let pickerView = UIPickerView(frame: .zero)
private var lastSelectedRow: Int?
public var pickerData: [Any] = []
public var displayNameHandler: PickerTextFieldDisplayNameHandler?
public var itemSelectionHandler: PickerTextFieldItemSelectionHandler?
override init(frame: CGRect) {
super.init(frame: frame)
self.configureView()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
self.configureView()
}
override func caretRect(for position: UITextPosition) -> CGRect {
return .zero
}
private func configureView() {
self.pickerView.delegate = self
self.pickerView.dataSource = self
self.inputView = pickerView
let toolbar = UIToolbar()
toolbar.barStyle = .default
toolbar.sizeToFit()
let spaceButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(doneButtonTapped))
toolbar.setItems([spaceButton, doneButton], animated: false)
self.inputAccessoryView = toolbar
}
private func updateText() {
if self.lastSelectedRow == nil {
self.lastSelectedRow = 0
}
if self.lastSelectedRow! > self.pickerData.count {
return
}
let data = self.pickerData[self.lastSelectedRow!]
self.text = self.displayNameHandler?(data)
}
@objc func doneButtonTapped() {
self.updateText()
self.resignFirstResponder()
}
}
extension PickerTextField: UIPickerViewDelegate {
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
let data = self.pickerData[row]
return self.displayNameHandler?(data)
}
}
extension PickerTextField: UIPickerViewDataSource {
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return self.pickerData.count
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
self.lastSelectedRow = row
self.updateText()
let data = self.pickerData[row]
self.itemSelectionHandler?(row, data)
}
}
根据我的理解,您想实现以下行为:
- 您想在文本字段内的选择器视图中显示用户选择的内容。
- 但是您不希望用户在文本字段中插入文本后更改文本。
我会使用 UITextField
和 UIPickerView
的委托方法。
UIPickerViewDelegate
中有一个方法可以让您知道用户选择了哪一行:
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
textField.text = "Hello \(row)"
}
在这里,您可以将文本设置为解决 (1) 的文本字段。
您还可以使用 UITextFieldDelegate
中的方法来防止用户在文本字段中输入内容。
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
return false
}
这可以防止用户在文本字段中键入任何内容。这解决了(2)。但是,光标仍会显示,这可能会使用户感到困惑。他可能认为他可以通过闪烁的光标向文本字段中输入内容,但实际上他不能。
当然,您必须像这样将文本字段 inputView
添加到您的自定义选择器视图中:
textField.inputView = myPickerView
我希望这能回答您的问题:)
我想知道如何阻止用户编辑 UITextField 而不是用户交互。我想在这里做的是当用户点击文本字段时,UIPickerView 从底部弹出,用户可以 select 选择器视图中的项目并将其显示在文本字段上。但我不希望用户能够编辑文本字段。我想为下面的 class 执行此操作。
import UIKit
typealias PickerTextFieldDisplayNameHandler = ((Any) -> String)
typealias PickerTextFieldItemSelectionHandler = ((Int, Any) -> Void)
class PickerTextField: UITextField {
private let pickerView = UIPickerView(frame: .zero)
private var lastSelectedRow: Int?
public var pickerData: [Any] = []
public var displayNameHandler: PickerTextFieldDisplayNameHandler?
public var itemSelectionHandler: PickerTextFieldItemSelectionHandler?
override init(frame: CGRect) {
super.init(frame: frame)
self.configureView()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
self.configureView()
}
override func caretRect(for position: UITextPosition) -> CGRect {
return .zero
}
private func configureView() {
self.pickerView.delegate = self
self.pickerView.dataSource = self
self.inputView = pickerView
let toolbar = UIToolbar()
toolbar.barStyle = .default
toolbar.sizeToFit()
let spaceButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(doneButtonTapped))
toolbar.setItems([spaceButton, doneButton], animated: false)
self.inputAccessoryView = toolbar
}
private func updateText() {
if self.lastSelectedRow == nil {
self.lastSelectedRow = 0
}
if self.lastSelectedRow! > self.pickerData.count {
return
}
let data = self.pickerData[self.lastSelectedRow!]
self.text = self.displayNameHandler?(data)
}
@objc func doneButtonTapped() {
self.updateText()
self.resignFirstResponder()
}
}
extension PickerTextField: UIPickerViewDelegate {
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
let data = self.pickerData[row]
return self.displayNameHandler?(data)
}
}
extension PickerTextField: UIPickerViewDataSource {
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return self.pickerData.count
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
self.lastSelectedRow = row
self.updateText()
let data = self.pickerData[row]
self.itemSelectionHandler?(row, data)
}
}
根据我的理解,您想实现以下行为:
- 您想在文本字段内的选择器视图中显示用户选择的内容。
- 但是您不希望用户在文本字段中插入文本后更改文本。
我会使用 UITextField
和 UIPickerView
的委托方法。
UIPickerViewDelegate
中有一个方法可以让您知道用户选择了哪一行:
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
textField.text = "Hello \(row)"
}
在这里,您可以将文本设置为解决 (1) 的文本字段。
您还可以使用 UITextFieldDelegate
中的方法来防止用户在文本字段中输入内容。
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
return false
}
这可以防止用户在文本字段中键入任何内容。这解决了(2)。但是,光标仍会显示,这可能会使用户感到困惑。他可能认为他可以通过闪烁的光标向文本字段中输入内容,但实际上他不能。
当然,您必须像这样将文本字段 inputView
添加到您的自定义选择器视图中:
textField.inputView = myPickerView
我希望这能回答您的问题:)