【Swift】制約を変更してテキストフィールドやテキストビューがキーボードと被らないようにする方法。(Swift 2.1、XCode 7.2)

2020年6月16日

UITextViewとキーボードが被るとどうなるか

前回までの記事でUITextView(以下、テキストビュー)の使い方と設定項目について説明した。本記事の手順はその記事の続きからになるので、実装を試す場合は「UITextViewの使い方」の記事を読んでから行うことをお勧めする。

Text View

 

キーボードを使ってフィールドに文字列を入力することができるようになったが、もし、キーボードと被りそうな位置にテキストビューが配置されていたらどうなると思うか。

以下の動画のように、キーボードが邪魔でテキストビューの内容が全く見えなくなるので、誤入力の無いこと祈りながら入力を続けることになる。

 

「最初からキーボードと被らない位置にテキストビューを配置しておけばいいじゃないか。」と思うかも知れないが、デザインの都合上どうしても画面下部にテキストビューやテキストフィールドを置きたいことがある。

そんなときはキーボードに押し出されるようにテキストビューの位置を上にずらすことで対応する。

 

制約とソースコードのコネクションを確立する

テキストビューのずらしを実際にやってみよう。今回はソースコードから制約を変更してテキストビューをずらす動きを実装する。

まず、テキストビューをキーボードと被りそうな場所に移動する(下図赤矢印)。続いて、紫枠のPINボタンを押して吹き出しの設定画面を表示させる。黄緑枠の2つのマークをクリック、WidthとHeightにチェックを入れて「Add 4 Constraints」ボタンを押す。これで、サイズと距離の制約が追加された。

UITextViewに制約を追加

 

次に、下図赤枠のアシスタントエディタボタンを押してViewController.swiftを表示する。画面下端からの制約(Bottom Layout…)をドラッグ&ドロップでソースコードまで運んで吹き出しの設定画面を表示させる(下図青矢印)。

Connectionに「Outlet」、Nameに「testConstraint」を入力し、Connectボタンを押す。これで、ソースコードから先ほど追加した制約を操作できるようになった。

制約とソースコードのコネクションを確立する

テキストビューとキーボードの被りを判定する方法

キーボードが現れるときに無条件でテキストビューをずらすのでは無く、キーボードがテキストビューと被る場合のみ、必要な長さだけ画面上部に向かってずらしたい。

ではどのように被る被らないを判定するのか。それは画面上端から部品までのY軸方向の距離をもとに判定する。

Y軸方向の距離として考えられるのは、下図のように画面上端から部品上端までの距離(最小距離)と画面上端から部品下端までの距離(最大距離)である。その中で、被りが確定するのはテキストビューの最大距離がキーボードの最小距離よりも大きい場合である。

テキストビューとキーボードが被るかのイメージ

 

ソースコードを実装する

上記の方法で判定するにはキーボードの座標を知る必要がある。しかし、テキストビューのデリゲートメソッドではキーボードの座標を取得することはできない。

そこで利用するのがNSNotificationCenterクラスの通知機能である。このクラスについては別の記事で説明するが、指定したイベントが発生したときに指定したメソッドを呼び出してくれるクラスである。呼び出しメソッドの引数からキーボードの座標を取得できる。

具体的には、ViewController.swiftを開き、viewDidLoadメソッドに以下のコードを追加する。

 

続いて、以下のメソッドを追加する。

テキストビューとキーボードが被る場合は被った長さを制約に加算する処理をしている。また、キーボードがテキストビューを押し出す感じを表現するために、UIViewのanimatedWithDurationメソッドを利用してアニメーションを行った。

変数allYは被った長さの変数で、キーボードを閉じるときのメソッドでも利用するのでクラス変数としてメソッドの外で定義しておくこと。

 

前回の記事で追加した「閉じるボタンで呼び出されるメソッド」に、テキストビューの位置を元に戻す処理を追加する。

allYの値が0より大きければテキストビューは移動されていると判断し、制約から被った長さをマイナスしている。

 

結果、ViewController.swiftは以下のようになる。

 

以下は実際のプレイ動画

 

次回から、Scroll Viewを用いて大きい部品をスクロールする方法について説明するが、その中でScroll VIewを用いてテキストビューを移動させる方法についても説明する。