Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
89
Help us understand the problem. What is going on with this article?
@ShinokiRyosei

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

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

サンプルコード

89
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
89
Help us understand the problem. What is going on with this article?