Recently, I need to solve the problem that the input method of Apple system blocks the input box in the project. The expected results are as follows:

  1. If the input box will be blocked after the keyboard pops up, the input box will move up with the keyboard, and the input box will always be 4pt above the keyboard when the input method is switched.
  2. If the input box is not blocked after the keyboard is ejected, but is blocked after the input method is switched, the input box needs to be moved up after the switch, and the input box should always be 4pt above the keyboard when the input method is switched.

Effect hint: /

To be added

/

A background.

Development environment: iOS14.2 + Xcode V12.2 + Swift5 Device: iPhoneSE (other models tested valid) page with automatic layout

Page structure: /

To be added

/

Two. Implementation method

Add notifications to viewWillAppear for keyboard pop-up, collapse, and frame changes

override func viewWillAppear(_ animated: Bool) {super. ViewWillAppear (animated) / / keyboard pop-up monitor, solve the problem of keyboard input box blocking NotificationCenter. Default. The addObserver (self, the selector: #selector(keyboardWillAppear), name: UIResponder.keyboardWillShowNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(keyboardHasAppear), name: UIResponder.keyboardDidShowNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillDisappear), name: UIResponder.keyboardWillHideNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(keyboardFrameDidChange), name: UIResponder.keyboardDidChangeFrameNotification, object: nil) }Copy the code

(Related link: iOS keyboard notifications)

Add a member variable:

Private var keyboardFlag: Int =0 private var deltaHeight: CGFloat = 0 private nameFieldBottomHeight: CGFloat = 0 private var transformDistance: CGFloat = 0 // Page movement distanceCopy the code

Implement keyboardWillAppear:

@objc func keyboardWillAppear(noti: Notification) {// Get the high let keyboardSize = (noti.userinfo? [UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)? .cgRectValue let keyboardHeight = keyboardSize? . The height / / calculation input box and the difference in height between the soft keyboard let the rect = self. NickNameEditView. ContainerView .convert(self.nickNameEditView.containerView.bounds, to: Self.view) // Convert rect from the rect view to the target view, Returns in the target view view of the rect self. NameFieldBottomHeight = self. The bounds. The height - (the rect. Origin. Y + the rect. Size. Height) self.deltaHeight = (keyboardHeight ?? 0) - self.nameFieldBottomHeight if self.keyboardFlag == 0, Self. DeltaHeight > 0 {/ / keyboard turned out to be put, and keep out input box self. PageContainerView. Transform = CGAffineTransform (a: 1, b: 0, c: 0, d: 1, tx: 0, ty: -self. Deltaheight-4) self. TransformDistance = -self. Deltaheight-4 /* -4:Copy the code

Implement keyboardHasAppear:

@objc func keyboardHasAppear() {self.keyboardFlag = 1}Copy the code

Implement keyboardWillDisappear:

@ objc func keyboardWillDisappear () {if self. KeyboardFlag = = 0 {/ / pack up soft keyboard to restore the original offset self. PageContainerView. Transform = CGAffineTransform.identity self.transformDistance = 0 } }Copy the code

Implement keyboardFrameDidChange, solve the switching input method dynamic adjustment:

@objc func keyboardFrameDidChange(noti: Notification) {// Get high let keyboardSize = (noti.userinfo? [UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)? .cgRectValue let keyboardHeight = keyboardSize? . The height / / input box and the height of the soft keyboard bad self. DeltaHeight = (keyboardHeight?? 0) - (self. NameFieldBottomHeight + If self.keyboardFlag == 1 {// If the page did not move up before, the keyboard blocks the input box, and the page moves up; Page is up, before input box down to 4 pt above the keyboard if (self. TransformDistance = = 0 && self. DeltaHeight > 0) | | (self transformDistance! = 0) { self.pageContainerView.transform = CGAffineTransform(a: 1, b: 0, c: 0, d: 1, tx: 0, ty: -self.deltaHeight - 4) self.transformDistance = -self.deltaHeight - 4 } } }Copy the code

Click blank area to receive keyboard:

// Override func touchesBegan(_ touches: Set, with event: UIEvent?) { if self.nickNameEditView.nameTextField.isFirstResponder { self.keyboardFlag = 0 self.nickNameEditView.nameTextField.resignFirstResponder() } }Copy the code

Remove notifications in viewWillDisappear:

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)

    NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
    NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardDidShowNotification, object: nil)
    NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
    NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardDidChangeFrameNotification, object: nil)
}
Copy the code

Article source: blog.csdn.net/fusy0714/ar…