キーボードエクステンションの情報はネット上にそれなりに出回るようになりましたが、コンテナアプリ(以下親アプリ)内でユーザーの追加の有無に関係なく表示できるようにする情報が見当たらなかったのでここでご紹介します。
style="display:inline-block;width:336px;height:280px"
data-ad-client="ca-pub-3481943934845626"
data-ad-slot="8806407289">
最初に試したこと
親アプリ内でインストールなしで表示できる、と明確に書いている文章は僕が探した限りでは海外のこちらの記事の”Make the containing app (somewhat) useful”という項目のものが唯一でした。
A mini-editor using the keyboard so that users can try the keyboard before installing it. This can be fairly easily implemented by attaching a UIInputView and your keyboard’s UIInputViewController to a UITextView. See the Text Programming Guide for iOS for more information.
またこちらの海外の記事によると、カスタムキーボードを表示させるにはtextView.inputView
にカスタムキーボードのビューを代入し、textView.reloadInputViews()
を呼べばOKとのこと。
そこでまず試したのが以下。
let keyboardController = KeyboardViewController() myTextView.inputView = keyboardController.view myTextView.reloadInputViews()(※自分のカスタムキーボードは.viewを使用)
しかしこれでは表示されず。
普通のUIViewであれば
textView.inputView
への代入で表示されると思いますが、キーボードエクステンションはそうはいきません。前述の文章をよく読んでみると「by attaching a UIInputView and your keyboard’s UIInputViewController to a UITextView.」と書いてあり、どうやらUITextViewのinputViewControllerとKeyboardViewControllerを繋げないといけないようです。
しかし残念ながらSwiftではUITextViewのinputViewControllerをオーバーライドできないので、この部分だけObjective-Cファイルを使う必要があります。
Objective-CでUITextViewの拡張クラス作成
ヘッダーファイルはinterface記述のみでOK。
//// UITextView+TextInputMode.h @interface UITextView (TextInputMode) @end
実装ファイルでinputViewControllerをオーバーライド。
そのままではSwiftファイルであるKeyboardViewControllerを初期化できないので、KeyboardMediatorなる仲介クラス(Swiftファイル)を作って利用しています。
#import "UITextView+TextInputMode.h" #import "AppName-Swift.h" @implementation UITextView (TextInputMode) - (UIInputViewController *) inputViewController { //// Swiftファイル群との仲介クラス KeyboardMediator *mediator = [KeyboardMediator new]; //// カスタムキーボードのコントローラ取得 UIInputViewController *keyboardViewController = [mediator getKeyboardController]; //// サイズセット。originはたぶん反映されない。 keyboardViewController.view.frame = CGRectMake(0, [mediator getTopMargin], [mediator getScreenWidth], [mediator getCoardHeight]); //// inputViewへ代入しなくてもたぶん動作する self.inputView = keyboardViewController.view; NSLog(@"カスタムキーボードをセットします。\n"); return keyboardViewController; } @end仲介のKeyboardMediatorクラスではKeyboardViewControllerの初期化やframeサイズ、その他必要なデータを返すメソッドを記述しています。
そして最後に
return keyboardViewController
をすれば無事にカスタムキーボードが表示されると思います。ただし上記のコードは説明用にシンプルにしたもので、動作検証していないので各自で確認お願いします(怠け者ですみません笑)
僕の環境では
self.inputView = keyboardViewController.view
をしなくてもカスタムキーボードはちゃんと表示・動作しました。しかしこの場合はキーボードの位置(origin)調整ができなくなるようです。
これは位置調整のときは
textView.inputView.superview
のframeなどをいじる必要があるんですが、inputViewがnilになってしまうためです。システムキーボードに戻したい場合は
return [super inputViewController];
を記述すればOKです。その他の細かい挙動など
僕もまだ取り組み始めたばかりなので細かい動作は把握しきれてなく、どのタイミングで
inputView = nil
をすればいいのかなどがわかっていません。アプリがバックグラウンドから復帰したときなどはカスタムキーボードの挙動がおかしくなることが多いですね。
これはキーボードエクステンションとしての動作をしっかり安定させた上での話なので、やはり親アプリ側でのリソースの管理に問題がありそうです。
ほかに発見したのは、NSNotificationの
"applicationWillEnterBackground"
通知タイミングでカスタムキーボードを解放させるようにしていると、外付けのcommand + tabでアプリスイッチャーを表示させたタイミングで強制的に別アプリへ飛んでしまうことです。ユーザーとしてはけっこう煩わしいので気をつけた方が良さそうです。
もう1つは、外付けのファンクションキーにある「ソフトウェアキーボード表示キー」でシステムキーボードの表示をONにしてしまうと、
return [super inputViewController];
を実行してもシステムキーボードへ切り替わらなくなるので注意です。(この場合はファンクションキーでシステムキーボードを隠す)
カスタムキーボードのグローブボタンを押すと、カスタムキーボードはそのままで、押すたびに入力言語だけが変わっていきます。
今のところ分かっているのはこんなところです。
ではでは。