#背景
アプリ作ってて入力する時にTextFieldを使うケースがありますが、キーボードに隠れないように設定するのって結構だるいですよね。
そこでそのキーボードが出てきてもきちんと見えるようになる設定をしたCustomViewControllerを作りました。
#開発環境
Swift: version 4
Xcode: version 9.3
##使用方法①
もともとUIViewControllerを継承するはずですけど、これをTextFieldViewControllerに変更してください。
class ViewController: TextFieldViewController {
}
##使用方法②
テキトーにTextFieldを設置します。サンプルコードでは二つ用意して、storyboardの要素と紐づけました。
@IBOutlet weak var firstTextField: UITextField!
@IBOutlet weak var secondTextField: UITextField!
##使用方法③
次にdelegateの設定をします。
override func viewDidLoad() {
super.viewDidLoad()
self.firstTextField.delegate = self
self.secondTextField.delegate = self
}
##使用方法④
最後に、notificationCenterでviewを監視し、キーボードが現れる時と消える時に処理するための関数を設定します。
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.setUpNotificationForTextField()
}
#実装完了したソースコード
これらの設定をすると以下のようになります。
import UIKit
class ViewController: TextFieldViewController {
@IBOutlet weak var firstTextField: UITextField!
@IBOutlet weak var secondTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
self.firstTextField.delegate = self
self.secondTextField.delegate = self
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.setUpNotificationForTextField()
}
}
#ちなみに、作ったクラスの中身
import UIKit
class TextFieldViewController: UIViewController, UITextFieldDelegate {
private var activeTextField: UITextField?
internal func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
internal func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
self.activeTextField = textField
return true
}
internal func setUpNotificationForTextField() {
let notificationCenter = NotificationCenter.default
notificationCenter.addObserver(self, selector: #selector(self.handleKeyboardWillShowNotification(_:)), name: .UIKeyboardWillShow, object: nil)
notificationCenter.addObserver(self, selector: #selector(self.handleKeyboardWillHideNotification(_:)), name: .UIKeyboardWillHide, object: nil)
}
@objc private func handleKeyboardWillShowNotification(_ notification: Notification) {
let userInfo = notification.userInfo //この中にキーボードの情報がある
let keyboardSize = (userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
let keyboardY = self.view.frame.size.height - keyboardSize.height //画面全体の高さ - キーボードの高さ = キーボードが被らない高さ
let editingTextFieldY: CGFloat = (self.activeTextField?.frame.origin.y)!
if editingTextFieldY > keyboardY - 60 {
UIView.animate(withDuration: 0.25, delay: 0.0, options: .curveEaseIn, animations: {
self.view.frame = CGRect(x: 0, y: self.view.frame.origin.y - (editingTextFieldY - (keyboardY - 60)), width: self.view.bounds.width, height: self.view.bounds.height)
}, completion: nil)
}
}
@objc private func handleKeyboardWillHideNotification(_ notification: Notification) {
UIView.animate(withDuration: 0.25, delay: 0.0, options: .curveEaseIn, animations: {
self.view.frame = CGRect(x: 0, y: 0, width: self.view.bounds.width, height: self.view.bounds.height)
}, completion: nil)
}
}
#githubからダウンロード
一応projectとしてgithubにリポジトリを作成しているので、ダウンロードしたい方はこちらをご利用ください。
#追記 Swift 5でのコード
import UIKit
class TextFieldViewController: UIViewController, UITextFieldDelegate {
private var activeTextField: UITextField?
internal func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
internal func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
self.activeTextField = textField
return true
}
internal func setUpNotificationForTextField() {
let notificationCenter = NotificationCenter.default
notificationCenter.addObserver(self, selector: #selector(self.handleKeyboardWillShowNotification(_:)), name: UIResponder.keyboardWillShowNotification, object: nil)
notificationCenter.addObserver(self, selector: #selector(self.handleKeyboardWillHideNotification(_:)), name: UIResponder.keyboardWillHideNotification, object: nil)
}
@objc private func handleKeyboardWillShowNotification(_ notification: Notification) {
let userInfo = notification.userInfo //この中にキーボードの情報がある
let keyboardSize = (userInfo![UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
let keyboardY = self.view.frame.size.height - keyboardSize.height //画面全体の高さ - キーボードの高さ = キーボードが被らない高さ
let editingTextFieldY: CGFloat = (self.activeTextField?.frame.origin.y)!
if editingTextFieldY > keyboardY - 60 {
UIView.animate(withDuration: 0.25, delay: 0.0, options: .curveEaseIn, animations: {
self.view.frame = CGRect(x: 0, y: self.view.frame.origin.y - (editingTextFieldY - (keyboardY - 60)), width: self.view.bounds.width, height: self.view.bounds.height)
}, completion: nil)
}
}
@objc private func handleKeyboardWillHideNotification(_ notification: Notification) {
UIView.animate(withDuration: 0.25, delay: 0.0, options: .curveEaseIn, animations: {
self.view.frame = CGRect(x: 0, y: 0, width: self.view.bounds.width, height: self.view.bounds.height)
}, completion: nil)
}
}