【Swift】テキストフィールドがキーボードに隠れないよう対応


概要

UITextFieldを編集する際にキーボードが下から出てきて入力欄を隠してしまうので、キーボードの出現とともにView自体の位置をキーボードの高さ分上げて隠れないようにする。

キーボードや予測変換部分の出現を検知する

       override func viewDidAppear(_ animated: Bool) {
        //ここでUIKeyboardWillShowという名前の通知のイベントをオブザーバー登録をしている
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
        //ここでUIKeyboardWillHideという名前の通知のイベントをオブザーバー登録をしている
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
        NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
    }

    // UIKeyboardWillShow通知を受けて、実行される関数
    @objc func keyboardWillShow(notification: NSNotification) {
        // 小書きを入力中は、画面を上げる
        if TextField_SmallWritting.isEditing {
            guard let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue else { return }
            animateWithKeyboard(notification: notification) { keyboardFrame in
                if self.view.frame.origin.y == 0 {
                    self.view.frame.origin.y -= keyboardSize.height - 150
                } else {
                    let suggestionHeight = self.view.frame.origin.y + keyboardSize.height
                    self.view.frame.origin.y -= suggestionHeight - 150
                }
            }
        }
    }

キーボードが隠れた際にViewの位置も戻す

    // UIKeyboardWillHide通知を受けて、実行される関数
    @objc func keyboardWillHide(notification: NSNotification) {
        animateWithKeyboard(notification: notification) { _ in
            if self.view.frame.origin.y != 0 {
                self.view.frame.origin.y = 0
            }
        }
    }

キーボードのアニメーションに合わせてViewをアニメーションさせる

    func animateWithKeyboard(notification: NSNotification, animations: ((_ keyboardFrame: CGRect) -> Void)?) {
        // キーボードのdurationを抽出 *1
        let durationKey = UIResponder.keyboardAnimationDurationUserInfoKey
        let duration = notification.userInfo![durationKey] as! Double

        // キーボードのframeを抽出する *2
        let frameKey = UIResponder.keyboardFrameEndUserInfoKey
        let keyboardFrameValue = notification.userInfo![frameKey] as! NSValue

        // アニメーション曲線を抽出する *3
        let curveKey = UIResponder.keyboardAnimationCurveUserInfoKey
        let curveValue = notification.userInfo![curveKey] as! Int
        let curve = UIView.AnimationCurve(rawValue: curveValue)!

        let animator = UIViewPropertyAnimator(duration: duration, curve: curve) {
            // ここにアニメーション化したいレイアウト変更を記述する
            animations?(keyboardFrameValue.cgRectValue)
            self.view?.layoutIfNeeded()
        }
        animator.startAnimation()
    }

参考

【Swift】キーボードと一緒にViewも上げる方法
https://orangelog.site/swift/slide-view-with-keyboard/#:~:text=TextField%E3%81%AEdelegate%E3%82%92ViewController,%E5%90%8C%E6%99%82%E3%81%AB%E3%82%AD%E3%83%BC%E3%83%9C%E3%83%BC%E3%83%89%E3%81%8C%E9%9A%A0%E3%82%8C%E3%81%BE%E3%81%99%E3%80%82 
【Swift】キーボードに合わせてViewをアニメーションさせる
https://qiita.com/_asa08_/items/1e40a2ac8de7bfb30b1b