繁体   English   中英

存在键盘时如何管理 UITextField 向上移动 - 如果存在多个 textFields?

[英]How to manage UITextField move up when the keyboard is present - in case of multiple textFields are present?

这是我的视图控制器。

在此处输入图片说明

当键盘覆盖屏幕底部的 textFields 时,我试图将 textFields 向上移动。 这是我完成的代码:

    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
    }

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

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

所需的更改是什么?

通常,您可以在文本字段上使用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约束greaterThan一个出口拖到您的代码中。 然后你需要做的就是

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM