Swift4 テキストフィールドをキーボードに隠れないように変更
基本的な考え
スクロールビューをStoryBoardへ配置、IBOutlet 接続
まず入力されたテキストフィールドを取得(座標値)
Notificationにより、画面サイズ、キーボードのサイズを取得
テキストフィールドの位置が、キーボドサイズより小さければ、上方向へスクロール (contentOffset.y)
入力後はスクロールを0に戻す
以上の流れです。
では実装
テキストフィールドに入力開始時に呼ばれるデリゲートメソッド
ここにはメンバ変数に入力されたテキストフィールドを渡しているだけ。 どのテキストフィールドを呼ばれても、ここが呼ばれる。
引数がtextFieldで、編集に入ったテキストフィールドをメンバにわたす.
それをメンバ変数に持っておく。座標をメンバに持っておく
呼び出し時
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool { //メンバ(座標保持)に現在入力されている textFieldを渡す。 txtActiveField = textField return true }
上記で詰め込んだメンバ変数 ただのUITextField型で良い
//メンバ var txtActiveField:UITextField?
ここで画面サイズを取得して、画面の一番上をget マージンを8pxにしてセットしている
//この関数名は適当で良い、下記のセレクターで渡している。 @objc func handleKeyboardWillShowNotification(notification: Notification) { //userInfoにはキーボードの位置とサイズが、辞書型で入っている let userInfo = notification.userInfo! //userInfoからキーボードのフレームサイズを取得 let keyboardScreenEndFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue //myBoudSize= 画面サイズ let myBoudSize:CGSize = UIScreen.main.bounds.size //origin.yはテキストフィールドの左上が取得できる 画面の座標系は左上が0.0 右下へ大きくなる let textLimit = txtActiveField!.frame.origin.y + txtActiveField!.frame.height + 8.0 let kbdLmit = myBoudSize.height - keyboardScreenEndFrame.size.height if textLimit >= kbdLmit{ scrollView.contentOffset.y = textLimit - kbdLmit } }
scrollViewは画面に配置しているもの
@IBOutlet weak var scrollView: UIScrollView!
Notificationの構造体に移行されたようだ
またuserinfo はハッシュ
public struct Notification : ReferenceConvertible, Equatable, Hashable { public typealias ReferenceType = NSNotification /// Storage for values or objects related to this notification. public var userInfo: [AnyHashable : Any]?
UIKeyboardFrameEndUserInfoKeyはアップルのグローバル変数
スクリーン座標でキーボードの終了フレーム矩形を識別するCGRectを含むNSValueオブジェクトのキー。フレームの四角形は、デバイスの現在の向きを反映しています。
上記関数をセレクターで渡す。
画面呼び出すたびに呼ばれるviewWillAppearにセット
override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(true) let notification = NotificationCenter.default //addObserverにセットすることで監視してくれる notification.addObserver(self, selector: #selector(handleKeyboardWillShowNotification(notification:)) , name: .UIKeyboardWillShow, object: nil) }
addObserverの関数定義
func addObserver(_ observer: Any, selector aSelector: Selector, name aName: NSNotification.Name?, object anObject: Any?)
observer :登録するオブジェクト
ここはこのクラスで宣言しているのでself
aSelector :通知を送付するメソッドを指定する。そのメソッドは一つだけ引数(オブジェクト)を保つ必要がある。
selectorの後に(関数名(引数))
aName :オブザーバーを登録する通知の名前。 .UIKeyboardWillShow
anObject:オブザーバが受信したい通知を持つオブジェクト。つまり、この送信者によって送信された通知のみがオブザーバに配信される
//閉じるときの処理 アップルのデリゲートメソッド 自動的に呼ばれる func textFieldShouldEndEditing(_ textField: UITextField) -> Bool { self.view.endEditing(true) return true } //閉じるときの処理 縦スクロールの値に0を入れる func handleKeyboardWillHideNotification(notification: Notification) { scrollView.contentOffset.y = 0 }