キーボードに消えて欲しい
なぜデフォルトで支援されないのか…
iPhone開発においてUITextViewやUITextFieldを使うと、デフォルトではその領域タッチでキーボードが出現します。しかし!編集が終わった後でそのキーボードを消す手段は提供されていません。iPhoneアプリケーションには多種多様な形が考えられるので選択肢を与えるのはいいと思いますが、せめてデフォルトで何らかの方法を用意しておいて欲しいものです。(キーボードにReturnの他にDoneボタンを用意するとか)
どのようにキーボードを消すかというのはいくつかやり方があって、いろいろ考えたのでまとめ。
まずキーボードを消す方法
そもそもキーボードはどうやって消せばいいのか。それにはまずFirstResponderとは何かを知る必要があります。これはユーザーの操作に対して最初に反応するオブジェクトのことで、キーボードが出現しているとき、UITextViewやUITextFieldはこのFirstResponderになっています。つまり、FirstResponderでなくなれば、キーボードは消える…!?
[textView resignFirstResponder];
これでキーボードは消えます。これを踏まえて「どのように消す」かということを考えてみましょう。ちなみにresignFirstResponderの逆のメソッドはbecomeFirstResponderです。参考までに…。
ReturnボタンをDoneボタンにする
UITextViewにしろ、UITextFieldにしろ、ReturnボタンをDoneボタンとして機能させることが可能です。しかし、当然こうするとReturnボタンの本来の機能である改行ができなくなります。
textField.returnKeyType = UIReturnKeyDone;
textField.delegate = self;
として、ReturnボタンをDoneボタンにして、デリゲートを指定し、デリゲートに指定したクラスに次のメソッドを実装します。
- (BOOL)textFieldShouldReturn:(UITextField *)textField { [textField resignFirstResponder]; return YES; }
これでReturnボタンがDoneボタンとしての機能を持ちます。
そもそもUITextViewとUITextFieldの違いというのは僕の認識では
- UITextViewは改行できる。テキスト消去のボタン(xボタン)がない。枠は自前。
- UITextFieldは改行できない。テキスト消去のボタン(xボタン)がある。枠が綺麗。
という感じなので、UITextFieldではReturnボタンの意味はあまりありません。そのため、Returnボタンに編集終了という機能を持たせるのはありだと思います。しかし、UITextViewではテキストの改行が可能なので、やはりReturnボタンには改行ボタンとしての機能を持っていて欲しいところです。
見えないボタンを使ってキーボードを消す
キーボードではない領域を見えないボタンにして、そこをタッチしたらキーボードが消えるようにします。見えないボタンはカスタムボタンを使うと作成できます。
customButton = [UIButton buttonWithType:UIButtonTypeCustom];
このボタンのアクションとしてキーボードを消す処理をしてあげればいいわけです。しかし、これにも問題があって、編集中にUITextViewの領域を長押しすることでカーソルの移動をすることができるのですが、透明なカスタムボタンを上に置いてしまうとそれができなくなります。
ナビゲーションバーにDoneボタン
NSNotificationCenterを使うと、キーボードの表示・非表示のタイミングで通知を受け取ることができるので、これを使って、キーボードが表示されたらナビゲーションバーにDoneボタンを設置し、キーボードが消えたらナビゲーションバーのDoneボタンを消すということができます。いろいろ考えた結果これが最良の選択肢ではないかと思いました。
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidAppear:) name:UIKeyboardDidShowNotification object:nil]; [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(keyboardDidDisappear:) name:UIKeyboardDidHideNotification object:nil];
これで、キーボードが出現するタイミングでkeyboardDidAppearメソッドが、消えるタイミングでkeyboardDidDisappearメソッドが呼び出されるようになります。あとは、keyboardDidAppearメソッドの中でDoneボタンをナビゲーションバーに設置し、keyboardDidDisappearメソッドの中でDoneボタンを消してやればいいというわけです。こんな感じになる。