Edited at

【Swift】UITextField, UITextViewがキーボードで隠れるのを防ぐ(UIScrollViewを使わずに)

More than 1 year has passed since last update.


はじめに

UITextFieldを画面に配置したはいいけど、下の写真のようにキーボードが出てくると隠れるというのはよくあることだと思います。

UIScrollViewを使ったりしている方法がありますが、画面にUIScrollViewを配置したりするのは面倒なので、画面をそもそもずらす方法を見つけたので、それをXcode8, Swift3で実装しました。

アートボード 1.png


コード


実装前


ViewController.swift

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)で呼び出します。

それぞれのメソッドは以下のように設定します。


ViewController.swift

    // 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のメソッドを設定します。


ViewController.swift

    // キーボードが現れた時に、画面全体をずらす。

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
})
}


以上で、完了です。

以下にすべてのコードを載せておきます。


完成品


ViewController.swift


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をキーボードに隠されず、高さが動的に変わるようにする


サンプルコード

https://github.com/ShinokiRyosei/Keyboard-Sampler