以前こちらの記事で(TextField, TextViewがキーボードに隠れてしまう問題)
キーボードを表示させた時に、textFieldやtextViewにかぶらないようにスクロールする方法を紹介しました。
しかし、これはscrollViewの上にtextFieldやtextViewを置いていることが前提になります。
例えばtableViewの下にtextFieldを持ってきて、送信したものがすぐにセルに反映させたいような仕様にしたい時は上記の記事のやり方では上手くいきません。
以下のような場合です。
tableViewとtextFieldが並列の関係になり、どちらも親要素にUIViewをとります。
このままでは、tableViewはキーボードの高さ分だけスクロールされますが、textFieldがスクロールされません。これはtextFieldがUIViewを親にとるからです。
解決策として、今回のような場合は UIViewごとスクロール
させます!
そこで使うのがaffin変換
というやり方です!
#Affine変換とは
Affine変換とはユークリッド幾何学的な線型変換と平行移動の組み合わせによる図形や形状の移動、変形方式です。(コトバンク調べ)
と難しい用語がでてきてよくわからないので、要は図形を移動、回転、左右反転、拡大、縮小などといった変換ができるということです。
今回はAffine変換をUIViewに対して適用します。UIViewはtransformというプロパティを保有しています。transformプロパティに値を代入することで、UIView を拡大・縮小・回転させることができます。Affine変換を行うにはCoreGraphicsを利用したCGAffineTransform☓☓☓☓メソッドを使います。☓☓☓☓以下のところには変換用途によっていろいろなメソッドが用意されているのでぜひ調べてみてください。
今回使うのはCGAffineTransformMakeTranslation
メソッドです!これは平行移動をするためのメソッドで第一引数にx座標の移動距離
、第二引数にy座標の移動距離
をとります。
##以下の様なコードになります
通知に関しては前回記事同様NSNotificationCenterを使います
※tableView, textFieldに関しては新たに設定して下さい
他は以前の記事と同様のコードです。
func handleKeyboardWillShowNotification(notification: NSNotification) {
//郵便入れみたいなもの
let userInfo = notification.userInfo!
//キーボードの大きさを取得
let keyboardRect = (userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue()
let duration: NSTimeInterval = ((userInfo[UIKeyboardAnimationDurationUserInfoKey])?.doubleValue)!
UIView.animateWithDuration(duration) { () -> Void in
//CGAffineTransformMakeTranslationメソッドを使い、平行移動を行う。(CoreGraphicsに定義されている)
//第一引数にx方向の移動距離を取り、第二引数にy方向の移動距離を取る
//y座標をキーボードの高さ分取得(上に引き上げるのでマイナスをつける)
let transform: CGAffineTransform = CGAffineTransformMakeTranslation(0, -keyboardRect.size.height)
//UIView を拡大・縮小・回転させることができるtransformプロパティに値をセット
self.view.transform = transform
}
}
//ずらした分を戻す処理
func handleKeyboardWillHideNotification(notification: NSNotification) {
let userInfo = notification.userInfo!
//キーボードの大きさを取得
let _ = (userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue()
let duration: NSTimeInterval = ((userInfo[UIKeyboardAnimationDurationUserInfoKey])?.doubleValue)!
UIView.animateWithDuration(duration) { () -> Void in
self.view.transform = CGAffineTransformIdentity
}
}
するとUIViewごとキーボードの高さ分だけスクロールされます。LINEのトークルームなんかもこんな仕様ですね。
今回はaffine変換を使ってスクロールさせましたが、他にもやり方はあるかと思います。もっといい方法があればぜひご教授頂けますと幸いですm(__)m