UITextFieldがキーボードに隠れないようにオフセットする




iPhoneでアプリの画面にたくさんTextFieldを配置した時、画面下の方のTextFieldを選択するとキーボードが下からニョキッと出てきてTextFieldを隠してしまう。もちろんそのままでも入力は可能だが、キーボードを仕舞うまでどう入力されているか分からないので不便である。
そこで、TextFieldを選択したときに隠れてしまう場合は表示をずらして隠れないようにしたい。ネットでサンプルを探したのだが、これというものが見当たらなかったので作ってみた。

InterfaceBuilderでまず全体にUIScrollViewを敷き詰めて、そこにUITextFieldを並べていく。
まず、(隠れてしまう)全てのTextFieldについて「Editing Did Begin」と「Editing Did End」の2つのイベントハンドラを定義しておく。この際、どのTextFieldに対しても同じメソッドを適用する。例えばそれぞれ – (void)textEditingDidBegin および - (void)textEditingDidEnd とする。
この時、InterfaceBuilderを使って普通にイベントハンドラを定義しようとすると両方とも「Editing Did End」イベントに結合してしまうので、ConnectionsInspectorで「Editing Did Begin」イベントから – (void)textEditingDidBegin メソッドに結合した方が良い。
また次のフィールドを宣言しておく。

1
2
3
4
5
6
7
@interface ViewController () {
    float _keyboardOffset; // 表示のオフセット(どれだけずらすか)
    float _offsetMargin; // 実際にオフセットを適用し始めるマージン
}
    :
    :
@end

そしてそれぞれ次のように初期化する。

1
2
3
4
5
6
7
8
- (void)viewDidLoad
{
    [super viewDidLoad];
    :
    :
    _keyboardOffset = 0.0f;
    _offsetMargin = 120.0f; // 4インチディスプレイの場合は 210.0f 程度
}

_offsetMargin というのは、例えば画面の上の方にあるTextFieldを選択したときは表示をずらす必要がないので、じゃあY座標がどこまでの範囲内ならオフセットしないかというのを決めておく必要がある。3.5インチの場合はだいたい120ピクセルぐらいまではずらさなくても大丈夫。4インチの場合は3.5インチの場合と90ピクセルくらい差があるのでマージンもそれだけ増やして大丈夫だ。

次に最初に定義したイベントハンドラを実装する。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- (IBAction)textEditingDidBegin:(UITextField *)sender {
    // オフセットすべきサイズを計算する
    CGRect textFieldRect = [sender frame];
    _keyboardOffset = MAX(0, textFieldRect.origin.y - _offsetMargin);
    // アクティブなTextFieldが表示されるようにオフセットする
    CGRect viewFrame = [self.scrollView frame];
    viewFrame.origin.y -= _keyboardOffset;
    self.scrollView.frame = viewFrame;
}

- (IBAction)textEditingDidEnd:(UITextField *)sender {
    // ScrollViewのオフセットを元の値に戻す
    CGRect viewFrame = [self.scrollView frame];
    viewFrame.origin.y += _keyboardOffset;
    self.scrollView.frame = viewFrame;
    _keyboardOffset = 0.0f;
}

尚、UITextFieldDelegateとかオフセット時のアニメーションとかは本題から外れるので適宜実装してください。

関連記事

Leave a Reply

アーカイブ