[Swift] UITextFieldにKeyboardが重なるときだけ全体を上にスライドさせる
環境
- Xcode 10.1
- Swift 4.2
- UIScrollViewは使いません
Keyboard開閉通知を追加する
Keyboardの開閉タイミングを知りたいのでNotificationを追加します。
class MyView : UIViewController { ...省略... override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) // Notificationを設定する let nc = NotificationCenter.default nc.addObserver(self, selector: #selector(self.keyboardWillShow(_:)), name: UIResponder.keyboardWillShowNotification, object: nil) nc.addObserver(self, selector: #selector(self.keyboardWillHide(_:)), name: UIResponder.keyboardWillHideNotification, object: nil) } // NotificationCenterからのキーボード表示通知に伴う処理 @objc func keyboardWillShow(_ notification: Notification) { } // NotificationCenterからのキーボード非表示通知に伴う処理 @objc func keyboardWillHide(_ notification: Notification) { } }
編集対象のTextFieldを保持する
KeyboardがTextFieldに重ならない場合にはスライドしたくないので、これを判別するためにどのTextFieldを編集しているかを覚えておきます。
textFieldShouldBeginEditingを使用してメンバ変数に編集対象のTextFieldを保持しておくようにします。
textFieldShouldBeginEditingを使用したいので、UIViewControllerにはUITextFieldDelegeteを追加します。
class MyView : UIViewController, UITextFieldDelegate { ...省略... // 編集中のTextFieldを保持する変数 private var _activeTextField: UITextField? = nil // TextFieldの編集直後に呼ばれる func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool { // 編集対象のTextFieldを保存する _activeTextField = textField return true; } }
Keyboardの開閉に合わせて全体をスライドさせる
Keyboardの開閉に合わせて全体のスライド幅を調整します。
TextFieldとKeyboardが重ならない場合にはスライドさせないように判定をしています。
問答無用でKeyboard分だけスライドしていい場合には判定はいらないので消してください。
// NotificationCenterからのキーボード表示通知に伴う処理 @objc func keyboardWillShowNotification(_ notification: Notification) { guard let textField = _activeTextField else { return } let rect = (notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue guard let keyboardHeight = rect?.size.height else { return } let mainBoundsSize = UIScreen.main.bounds.size let textFieldLimit = textField.frame.origin.y + textField.frame.height + 8.0 let keyboardLimit = mainBoundsSize.height - keyboardHeight if keyboardLimit <= textFieldLimit { let duration: TimeInterval? = notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double UIView.animate(withDuration: duration!, animations: { () in self.view.transform = CGAffineTransform(translationX: 0, y: -keyboardHeight) }) } } // NotificationCenterからのキーボード非表示通知に伴う処理 @objc func keyboardWillHideNotification(_ notification: Notification) { let duration: TimeInterval? = notification.userInfo?[UIResponder.keyboardAnimationCurveUserInfoKey] as? Double UIView.animate(withDuration: duration!, animations: { () in self.view.transform = CGAffineTransform.identity }) }
おしまい。
ディスカッション
ピンバック & トラックバック一覧
[…] MEMO このサイトを参考にさせてもらいました。 実際には、上記サイトでは、移動距離の計算をきちんと書いているのですが、そこまでいらないかなぁと思って、適当にしたバージョ […]