【问题标题】:How to manage UITextField move up when the keyboard is present - in case of multiple textFields are present?当键盘存在时如何管理 UITextField 向上移动 - 如果存在多个文本字段?
【发布时间】:2021-10-23 00:25:32
【问题描述】:

这是我的视图控制器。

我试图在键盘覆盖屏幕底部的文本字段时向上移动文本字段。这是我完成的代码:

    override func viewDidLoad() {
        super.viewDidLoad()
        
        txtFName.delegate = self
        txtLName.delegate = self
        txtCompany.delegate = self
        txtStreet1.delegate = self
        txtStreet2.delegate = self
        txtTown.delegate = self
        txtPin.delegate = self
        txtPhone.delegate = self
        txtEmail.delegate = self
        
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(self.keyBoardWillChange(notification:)),
            name: UIResponder.keyboardWillShowNotification, object: nil)
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(self.keyBoardWillChange(notification:)),
            name: UIResponder.keyboardWillHideNotification, object: nil)
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(self.keyBoardWillChange(notification:)),
            name: UIResponder.keyboardWillChangeFrameNotification, object: nil)

    deinit {
        NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
        NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
        NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
    }

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        print("Return Tapped")
        txtFName.resignFirstResponder()
        txtLName.resignFirstResponder()
        txtCompany.resignFirstResponder()
        txtStreet1.resignFirstResponder()
        txtStreet2.resignFirstResponder()
        txtTown.resignFirstResponder()
        txtPin.resignFirstResponder()
        txtPhone.resignFirstResponder()
        txtEmail.resignFirstResponder()
        view.frame.origin.y = 0
        return true
    }
    
    @objc func keyBoardWillChange(notification: Notification) {
        print("Keyboard will show: \(notification.name.rawValue)")
        view.frame.origin.y = -250
    }

现在,当我点击任何文本字段时,整个视图都在向上移动。 “txtFName”、“txtLName”.. 这些文本字段不可见。

我只想在点击“txtPin”、“txtPhone”、“txtEmail”时向上移动视图。即使出现键盘,其余文本字段也会保持在默认位置。

需要进行哪些更改?

【问题讨论】:

标签: ios swift


【解决方案1】:

通常,您可以在文本字段中使用 isFirstResponder 属性。如果为 true,则表示这是您希望在开始编辑时关注并向上移动的文本字段。

@objc private func keyBoardWillChange(notification: Notification) {
    let possibleTextFields: [UITextField] = [txtLName, txtCompany, txtStreet1, txtStreet2, txtTown, txtPin, txtPhone, txtEmail]
    let focusedTextField: UITextField? = possibleTextFields.first { $0.isFirstResponder }
    ...
}

现在您已经知道了,您仍然需要计算移动视图所需的偏移量

获取键盘框架:

guard let info = notification.userInfo else { return }
guard let value: NSValue = info[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue else { return }
let newFrame = value.cgRectValue

计算差异

有一些工具可以检查框架,允许您将框架转换为不同的坐标系(视图)

private func getVerticalDifference(keyboardFrame: CGRect, viewToFocus: UIView, panel: UIView) -> CGFloat {
    let keyboardInPanel = panel.convert(keyboardFrame, from: nil)
    let viewInPanel = panel.convert(viewToFocus.bounds, from: viewToFocus)
    
    return viewInPanel.maxY - keyboardInPanel.minY
}

我建议您将视图控制器的视图用于您的 panel 参数,它应该是没有被更改的东西(在您当前的代码中不是这种情况。避免更改视图控制器的视图框架) .

应用差异:

要应用差异,我建议您使用约束。将所有文本字段放在一个“面板”视图上。此视图最好也放入滚动视图中,以便用户可以在较小的设备上滚动浏览它。现在面板(或滚动视图)可以对视图控制器具有低优先级(例如 500)底部约束。然后将另一个高优先级底部约束设置为greaterThan,这意味着底部将被固定为“大于 X”,X 可以稍后设置。

现在您可以从greaterThan 约束中将一个出口拖到您的代码中。然后你需要做的就是

bottomConstraintOutlet.constant = max(0.0, getVerticalDifference(...))

【讨论】:

  • 感谢您的建议。但它已经通过其他方式解决了。
猜你喜欢
  • 1970-01-01
  • 2010-11-10
  • 1970-01-01
  • 2020-05-21
  • 2015-10-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多