LoginSignup
99
89

More than 5 years have passed since last update.

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

Last updated at Posted at 2016-12-09

はじめに

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

サンプルコード

99
89
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
99
89