打开时,UITextField被键盘部分隐藏

时间:2019-09-24 10:22:04

标签: swift uiscrollview uitextfield

我正在尝试创建UITextField元素的集合。我希望键盘上的next按钮跳到下一个字段,如果该字段已被键盘隐藏,请滚动到视图中。

这是我的尝试。它的工作与1个方面不同。

在关闭键盘后选择另一个(或相同)字段时,键盘会部分隐藏文本输入(请参见随附的gif)。

肉和土豆在ViewController扩展名之内。

class ViewController: UIViewController {

    var activeField: UITextField?
    var lastOffset: CGPoint!
    var keyboardHeight: CGFloat!

    let scrollView: UIScrollView = {
        let scrollView = UIScrollView()
        scrollView.translatesAutoresizingMaskIntoConstraints = false
        return scrollView
    }()

    let scrollViewContainer: UIStackView = {
        let view = UIStackView()
        view.axis = .vertical
        view.spacing = 10
        view.translatesAutoresizingMaskIntoConstraints = false
        return view
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        view.backgroundColor = .white

        view.addSubview(scrollView)
        scrollView.addSubview(scrollViewContainer)

        let totalFieldCount = 25

        for i in 1...totalFieldCount {
            let textField = createTextField(self, placeholder: "Field #\(i)", type: .default)

            textField.returnKeyType = i < totalFieldCount ? .next : .done
            textField.tag = i
            scrollViewContainer.addArrangedSubview(textField)
        }

        NSLayoutConstraint.activate([
            scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
            scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
            scrollViewContainer.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
            scrollViewContainer.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor),
            scrollViewContainer.topAnchor.constraint(equalTo: scrollView.topAnchor),
            scrollViewContainer.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
            scrollViewContainer.widthAnchor.constraint(equalTo: scrollView.widthAnchor)
        ])

        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)

        scrollView.keyboardDismissMode = .interactive
    }

    func createTextField(_ delegate: UITextFieldDelegate?, placeholder: String, type: UIKeyboardType, isSecureEntry: Bool = false) -> UITextField {
        let tf = UITextField(frame: .zero)

        tf.placeholder = placeholder
        tf.backgroundColor = .init(white: 0, alpha: 0.03)
        tf.borderStyle = .roundedRect
        tf.font = .systemFont(ofSize: 14)
        tf.keyboardType = type
        tf.autocapitalizationType = .none
        tf.autocorrectionType = .no
        tf.isSecureTextEntry = isSecureEntry

        tf.heightAnchor.constraint(equalToConstant: 40).isActive = true

        if let delegate = delegate {
            tf.delegate = delegate
        }

        return tf
    }

}

extension ViewController: UITextFieldDelegate {

    func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
        activeField = textField
        lastOffset = self.scrollView.contentOffset
        return true
    }

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        let nextTag = textField.tag + 1

           if let nextResponder = textField.superview?.viewWithTag(nextTag) {
               nextResponder.becomeFirstResponder()
           } else {
            activeField?.resignFirstResponder()
            activeField = nil
        }

           return true
    }
}

extension ViewController {
    @objc func keyboardWillShow(notification: NSNotification) {

        guard keyboardHeight == nil else { return }

        if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
            keyboardHeight = keyboardSize.height

            UIView.animate(withDuration: 0.3, animations: {
                self.scrollView.contentInset.bottom = self.keyboardHeight
            })

            guard let activeField = activeField else { return }

            let distanceToBottom = self.scrollView.frame.size.height - (activeField.frame.origin.y) - (activeField.frame.size.height)
            let collapseSpace = keyboardHeight - distanceToBottom

            guard collapseSpace > 0 else { return }

            UIView.animate(withDuration: 0.3, animations: {
                self.scrollView.contentOffset = CGPoint(x: self.lastOffset.x, y: collapseSpace + 10)
            })
        }
    }

    @objc func keyboardWillHide(notification: NSNotification) {
        UIView.animate(withDuration: 0.3) {
            self.scrollView.contentOffset = self.lastOffset
            self.scrollView.contentInset.bottom = 0
        }

        keyboardHeight = nil
    }
}

enter image description here

1 个答案:

答案 0 :(得分:0)

keyboardFrameBeginUserInfoKey替换为keyboardFrameEndUserInfoKey