【问题标题】:How to set TextField in InputAccessoryView as First Responder [Swift]如何将 InputAccessoryView 中的 TextField 设置为第一响应者 [Swift]
【发布时间】:2021-04-26 07:21:14
【问题描述】:

好的,所以我有一个带有 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()
}

}

问题是,当键盘出现将其设置为第一响应者而不是原始文本字段时,我不知道如何在 InputAccessoryView 中引用文本字段(图像中的“150”)。强>

我希望通过键盘输入来更改 InputAccessoryView 内 TextField 中的文本。现在原来的 textField 仍然是第一响应者。

我尝试在函数 (cellForRowAt) 内创建时将 inputTextField 设置为 becomeFirstResponder,但这显然为时过早,因为键盘还没有出现。

我研究了类似的问题/答案,但没有一个涉及如何在 InputAccessoryView 中引用 textField ——尤其是来自 tableViewCell 时。

【问题讨论】:

  • 您是否尝试过延迟异步调用becomeFirstResponder?试试:DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { textField.becomeFirstResponder() }
  • 这实际上是让 inputAccessoryView 文本字段响应的最佳方式,谢谢!

标签: ios swift uitextfield tableview inputaccessoryview


【解决方案1】:

首先我支持将其设为自定义视图而不是扩展,以便于访问文本字段

其次以您当前的方式访问它,像这样向您的文本字段添加标签

inputTextField.tag = 33

终于像这样访问文本字段

profileDataTextField.addToolbarInputAccessoryView()
gurad let field = profileDataTextField.inputAccessoryView.viewWithTag(33) else { return }
field.becomeFirstResponder()

【讨论】:

  • 好的,所以我得到了这个工作!但是,我现在如何从 self.endEditing(true) 上的 textField 中获取输入的值?
  • 使用field.text
【解决方案2】:

尝试通过延迟异步调用 becomeFirstResponder 以允许键盘初始化:

DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { 
    textField.becomeFirstResponder()
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-08-01
    • 2019-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-12
    相关资源
    最近更新 更多