はじめに
UITextField
を画面に配置したはいいけど、下の写真のようにキーボードが出てくると隠れるというのはよくあることだと思います。
UIScrollViewを使ったりしている方法がありますが、画面にUIScrollViewを配置したりするのは面倒なので、画面をそもそもずらす方法を見つけたので、それをXcode8, Swift3で実装しました。
コード
実装前
import UIKit
class ViewController: UIViewController, UITextFieldDelegate {
@IBOutlet var firstTextField: UITextField! {
didSet {
firstTextField.delegate = self
}
}
@IBOutlet var secondTextField: UITextField! {
didSet {
secondTextField.delegate = self
}
}
override func viewDidLoad() {
super.viewDidLoad()
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
}
これだと、キーボードがReturnキーを押したときに下がるだけの実装です。
ここから、NotificationCenter
を使って、キーボードが表示されたり消えたりすることを検知します。
そして、キーボードが表示されたり消えたときに、animate(withDuration duration: TimeInterval, animations: @escaping () -> Swift.Void)
を使って、画面全体をずらします。
実装
まずNotification
を設定するメソッドと削除するメソッドを用意し、それぞれviewWillAppear(_ animated: Bool)
とviewWillDisappear(_ animated: Bool)
で呼び出します。
それぞれのメソッドは以下のように設定します。
// Notificationを設定
func configureObserver() {
let notification = NotificationCenter.default
notification.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
notification.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
// Notificationを削除
func removeObserver() {
let notification = NotificationCenter.default
notification.removeObserver(self)
}
Notification
に設定したselector
のメソッドを設定します。
// キーボードが現れた時に、画面全体をずらす。
func keyboardWillShow(notification: Notification?) {
let rect = (notification?.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue
let duration: TimeInterval? = notification?.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? Double
UIView.animate(withDuration: duration!, animations: { () in
let transform = CGAffineTransform(translationX: 0, y: -(rect?.size.height)!)
self.view.transform = transform
})
}
// キーボードが消えたときに、画面を戻す
func keyboardWillHide(notification: Notification?) {
let duration: TimeInterval? = notification?.userInfo?[UIKeyboardAnimationCurveUserInfoKey] as? Double
UIView.animate(withDuration: duration!, animations: { () in
self.view.transform = CGAffineTransform.identity
})
}
以上で、完了です。
以下にすべてのコードを載せておきます。
完成品
import UIKit
class ViewController: UIViewController, UITextFieldDelegate {
@IBOutlet var firstTextField: UITextField! {
didSet {
firstTextField.delegate = self // デリゲートをセット
}
}
@IBOutlet var secondTextField: UITextField! {
didSet {
secondTextField.delegate = self // デリゲートをセット
}
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.configureObserver()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
self.removeObserver() // Notificationを画面が消えるときに削除
}
// Notificationを設定
func configureObserver() {
let notification = NotificationCenter.default
notification.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
notification.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
// Notificationを削除
func removeObserver() {
let notification = NotificationCenter.default
notification.removeObserver(self)
}
// キーボードが現れた時に、画面全体をずらす。
func keyboardWillShow(notification: Notification?) {
let rect = (notification?.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue
let duration: TimeInterval? = notification?.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? Double
UIView.animate(withDuration: duration!, animations: { () in
let transform = CGAffineTransform(translationX: 0, y: -(rect?.size.height)!)
self.view.transform = transform
})
}
// キーボードが消えたときに、画面を戻す
func keyboardWillHide(notification: Notification?) {
let duration: TimeInterval? = notification?.userInfo?[UIKeyboardAnimationCurveUserInfoKey] as? Double
UIView.animate(withDuration: duration!, animations: { () in
self.view.transform = CGAffineTransform.identity
})
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder() // Returnキーを押したときにキーボードを下げる
return true
}
}
参考URL
TextViewをキーボードに隠されず、高さが動的に変わるようにする
サンプルコード