问题描述
好的,所以我有一个带有 textField 的 tableView,当用户点击 tableView 中的 textField 时,键盘会显示一个自定义 InputAccessoryView。它看起来像这样:
这是创建自定义 InputAccessoryView 的代码,我在 cellForRowAt 和 textFieldDidBeginEditing(如下)为 tableView(每行执行不同的功能)中尝试过。
func textFieldDidBeginEditing(_ textField: UITextField) {
print("textFieldDidBeginEditing")
if textField.tag == 1 {
profileDataTextField.addToolbarInputAccessoryView()
}
}
我已经将它创建为 UITextField 的扩展:
extension UITextField {
func addToolbarInputAccessoryView() {
let screenWidth = UIScreen.main.bounds.width
// Create Main Container View
let mainContainerView = UIView()
mainContainerView.backgroundColor = .clear
mainContainerView.frame = CGRect(x: 0,y: 0,width: screenWidth,height: 120)
// Create heading Label
let label = UILabel()
label.textColor = .white
label.font = UIFont(name: "BrandonGrotesque-Bold",size: 20)
label.text = "Enter New Weight"
label.widthAnchor.constraint(equalToConstant: screenWidth).isActive = true
label.heightAnchor.constraint(equalToConstant: 30.0).isActive = true
label.textAlignment = .center
// Create Input Container View
let inputContainerView = UIView()
inputContainerView.backgroundColor = .white
inputContainerView.heightAnchor.constraint(equalToConstant: 80.0).isActive = true
inputContainerView.widthAnchor.constraint(equalToConstant: screenWidth).isActive = true
// Create inputTextField
let inputTextField = UITextField()
inputTextField.translatesAutoresizingMaskIntoConstraints = false
inputTextField.placeholder = "150"
inputTextField.textAlignment = .left
inputTextField.textColor = .darkGray
inputTextField.font = UIFont(name: "BrandonGrotesque-Bold",size: 50)
inputTextField.backgroundColor = .white
inputTextField.layer.cornerRadius = 4
inputTextField.layer.masksToBounds = true
inputTextField.borderStyle = .none
// Create metricTextField
let metricLabel = UILabel()
metricLabel.textColor = .darkGray
metricLabel.font = UIFont(name: "BrandonGrotesque-Bold",size: 18)
metricLabel.text = "lbs"
metricLabel.textAlignment = .left
// Create Done button
let doneButton = UIButton()
doneButton.backgroundColor = .systemIndigo
doneButton.setTitle("Done",for: .normal)
doneButton.titleLabel?.font = UIFont(name: "BrandonGrotesque-Bold",size: 20)
doneButton.cornerRadius = 4
doneButton.translatesAutoresizingMaskIntoConstraints = false
doneButton.addTarget(self,action: #selector(doneTapped),for: .touchUpInside)
// Create cancel button
let cancelButton = UIButton()
cancelButton.backgroundColor = .systemRed
cancelButton.setTitle("Cancel",for: .normal)
cancelButton.titleLabel?.font = UIFont(name: "BrandonGrotesque-Bold",size: 20)
cancelButton.cornerRadius = 4
cancelButton.translatesAutoresizingMaskIntoConstraints = false
cancelButton.addTarget(self,action: #selector(cancelTapped),for: .touchUpInside)
// Main Stack View
let mainStackView = UIStackView()
mainStackView.axis = .vertical
mainStackView.distribution = .fill
mainStackView.alignment = .fill
mainStackView.spacing = 10.0
mainStackView.backgroundColor = .clear
// Toolbar StackView
let toolbarStackView = UIStackView()
toolbarStackView.axis = .horizontal
toolbarStackView.distribution = .fillEqually
toolbarStackView.alignment = .fill
toolbarStackView.spacing = 20.0
toolbarStackView.backgroundColor = .white
// Input Stackview
let inputStackView = UIStackView()
inputStackView.axis = .horizontal
inputStackView.distribution = .equalCentering
inputStackView.alignment = .center
inputStackView.spacing = 5.0
inputStackView.backgroundColor = .white
// Put it all together
mainStackView.addArrangedSubview(label)
inputStackView.addArrangedSubview(inputTextField)
inputStackView.addArrangedSubview(metricLabel)
toolbarStackView.addArrangedSubview(cancelButton)
toolbarStackView.addArrangedSubview(inputStackView)
toolbarStackView.addArrangedSubview(doneButton)
toolbarStackView.translatesAutoresizingMaskIntoConstraints = false
inputContainerView.addSubview(toolbarStackView)
mainStackView.addArrangedSubview(inputContainerView)
mainStackView.translatesAutoresizingMaskIntoConstraints = false
toolbarStackView.leadingAnchor.constraint(equalTo: inputContainerView.leadingAnchor,constant: 15).isActive = true
toolbarStackView.trailingAnchor.constraint(equalTo: inputContainerView.trailingAnchor,constant: -15).isActive = true
toolbarStackView.topAnchor.constraint(equalTo: inputContainerView.topAnchor,constant: 15).isActive = true
toolbarStackView.bottomAnchor.constraint(equalTo: inputContainerView.bottomAnchor,constant: -15).isActive = true
mainContainerView.addSubview(mainStackView)
inputAccessoryView = mainContainerView
}
@objc func cancelTapped() {
self.resignFirstResponder()
}
@objc func doneTapped() {
self.resignFirstResponder()
}
}
问题是,当键盘似乎将其设置为第一响应者而不是原始 textField 时,我不知道如何在 InputAccessoryView 中引用 textField(图像中的“150”)。
我希望来自键盘的输入更改 InputAccessoryView 中 TextField 中的文本。现在原来的 textField 仍然是第一响应者。
我已经尝试在函数 (cellForRowAt) 内创建时将 inputTextField 设置为 becomeFirstResponder,但这显然为时过早,因为键盘尚未出现。
我研究过类似的问题/答案,但没有一个涉及如何在 InputAccessoryView 中引用 textField——尤其是当来自 tableViewCell 时。
解决方法
首先我支持将其设为自定义视图而不是扩展程序,以便轻松访问文本字段
其次以您当前的方式访问它,像这样在文本字段中添加一个标签
inputTextField.tag = 33
最后像这样访问文本字段
profileDataTextField.addToolbarInputAccessoryView()
gurad let field = profileDataTextField.inputAccessoryView.viewWithTag(33) else { return }
field.becomeFirstResponder()
,
尝试延迟异步调用 becomeFirstResponder 以允许键盘初始化:
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
textField.becomeFirstResponder()
}