この投稿では、Android用のジェスチャー入力メソッドを作成する方法を説明します。 この入力方法は手書きに似ていますが、1つの制限があります。指を離さずに文字(数字、単語)を描画する必要があります。 実装には、入力メソッドとジェスチャ設定ユーティリティが含まれます。これは、Android SDKの例から再設計された「Gesture Builder」です。
キーボードを作成する
キーボードクラスを作成することから始めましょう。 すべての入力メソッドはInputMethodServiceに基づいて作成され、ジェスチャ認識のために、OnGesturePerformedListenerが含まれています。 認識の問題を回避するために、各言語には個別のファイルがあります。 これを行うには、2つのプロパティをクラスに追加します:言語のマップと現在の言語の名前。
// HashMap< , > private HashMap<String, GestureLibrary> mGestureLibMap; // private String mCurrentGestureLib = null;
言語のロードはloadLanguagesメソッドになります。このメソッドは、アプリケーションファイルディレクトリをスキャンし、すべてのコンテンツを言語としてロードします。
private void loadLanguages() { // "" File[] files = getFilesDir().listFiles(); mGestureLibMap = new HashMap<String, GestureLibrary>(); // "" for(int i = 0; i < files.length; i++) { GestureLibrary gestureLib = GestureLibraries.fromFile(files[i]); if (!gestureLib.load()) { Toast.makeText(this, "Can't load gestures " + files[i].getName(), Toast.LENGTH_LONG).show(); continue; } // mGestureLibMap.put(files[i].getName(), gestureLib); } if(mCurrentGestureLib == null || !mGestureLibMap.containsKey(mCurrentGestureLib)) { // mCurrentGestureLib = mGestureLibMap.keySet().toArray(new String[0])[0]; if(mGestureLibMap.containsKey(mCurrentGestureLib.toLowerCase())) mCurrentGestureLib = mCurrentGestureLib.toLowerCase(); } }
loadLanguagesは、キーボードが呼び出されるたびに呼び出されるonStartInputViewメソッドで呼び出されます。 このソリューションは、おそらく多くの言語でブレーキをかけますが、この方法では常に「新鮮な」ジェスチャーがあります。 最後のジェスチャ更新のファイルまたは静的プロパティでは扱いにくいかもしれませんが、標準セット(en、ru、09)でブレーキに気付かなかったので、私はそれをだましませんでした。
ジェスチャーはonGesturePerformedメソッドで認識されます(ジェスチャーの詳細については、 こちらをご覧ください )。 ジェスチャの名前が「@@」で始まる場合、その後にキーコードが続くと想定して、アプリケーションに送信します。 それが何か別のもので始まる場合、テキストとして送信します。 メソッド自体は次のようになります。
public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) { // ArrayList<Prediction> predictions = mGestureLibMap.get(mCurrentGestureLib).recognize(gesture); if (predictions.size() > 0) { // Prediction prediction = predictions.get(0); if(prediction.name.startsWith("@@")) { // @@, try { keyDownUp(Integer.valueOf(prediction.name.substring(2))); } catch(NumberFormatException e) { Log.w("GestureKeyboard", "NumberFormatException: " + e.getLocalizedMessage()); } } else { // getCurrentInputConnection().commitText(editString(prediction.name), prediction.name.length()); } } }
このメソッドでは、不明なeditStringメソッドに気付く場合があります。 このメソッドは、「Upper」ボタンと「Lower」ボタンの状態に応じて大文字と小文字を変更します。
private String editString(String in) { // lower, LowerCase if(mLowerLock.isChecked()) return in.toLowerCase(); // upper, UpperCase if(mUpperLock.isChecked()) return in.toUpperCase(); // return in; }
また、keyDownUpメソッドは、keyDownとkeyUpの2つのイベントをアプリケーションに送信します。 SoftKeyboardの例から取られたもので、次のようになります。
private void keyDownUp(int keyEventCode) { // keyDown keyUp getCurrentInputConnection().sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, keyEventCode)); getCurrentInputConnection().sendKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, keyEventCode)); }
さまざまな言語をダウンロードしたため、変更できます。 これらは、onLangClickとsetCurrentLanguageの2つのメソッドで変更されます。 onLangClickボタンをクリックすると、現在の言語の横にある言語のリストが表示されます。または、言語がない場合は最初の言語に変更されます。 言語を変更する場合、「Caps Lock」ボタンの状態も考慮されます。
public void onLangClick(View v) { // // String gestureNames[] = mGestureLibMap.keySet().toArray(new String[0]); boolean next = false; for(int i = 0; i < gestureNames.length; i++) { if(next) { // if(!mCurrentGestureLib.toLowerCase().equals(gestureNames[i].toLowerCase())) { // setCurrentLanguage(gestureNames, i); next = false; break; } continue; } if(mCurrentGestureLib.toLowerCase().equals(gestureNames[i].toLowerCase())) { // next = true; } } if(next) setCurrentLanguage(gestureNames, 0); // mLangSwither.setText(mCurrentGestureLib); } private void setCurrentLanguage(String gestureNames[], int index) { mCurrentGestureLib = gestureNames[index]; // LowerCase, if(mGestureLibMap.containsKey(gestureNames[index].toLowerCase())) { mCurrentGestureLib = gestureNames[index].toLowerCase(); } // , UpperCase if(mCapsLock.isChecked() && mGestureLibMap.containsKey(gestureNames[index].toUpperCase())) { mCurrentGestureLib = gestureNames[index].toUpperCase(); } }
大文字と小文字を変更するには、上、下、キャップの3つのボタンを使用します。 面白いのはキャップだけです。 言語は2つのレジスタに入れることができます。 レジスターは、言語の名前で書くことができます(例:enおよびEN)。 ただし、capsボタンはこれらのレジスタを切り替えるか、存在しない場合は、UpperボタンとLowerボタンの状態を変更します。
if(isChecked) { mLowerLock.setChecked(false); if(mGestureLibMap.containsKey(mCurrentGestureLib.toUpperCase())) { // UpperCase mUpperLock.setChecked(false); mCurrentGestureLib = mCurrentGestureLib.toUpperCase(); } else { // UpperCase, UpperLock mUpperLock.setChecked(true); } } else { mUpperLock.setChecked(false); if(mGestureLibMap.containsKey(mCurrentGestureLib.toLowerCase())) { // LowerCase mLowerLock.setChecked(false); mCurrentGestureLib = mCurrentGestureLib.toLowerCase(); } else { // LowerLock mLowerLock.setChecked(true); } } // mLangSwither.setText(mCurrentGestureLib);
UIを少し装飾すると、スクリーンショットに示されているものが判明しました。
入力メソッドクラスの準備ができました。AndroidManifest.xmlに次のようなものが必要になりました。
<service android:name="GestureKeyboard" android:permission="android.permission.BIND_INPUT_METHOD"> <intent-filter> <action android:name="android.view.InputMethod"/> </intent-filter> <meta-data android:name="android.view.im" android:resource="@xml/method"/> </service>
UIを少し装飾すると、 スクリーンショットに表示されているものが判明しました。
設定については言葉で説明します。 最初から、私はAndroid SDKからGesture Builderのソースを取得し、必要なソースとリソースをプロジェクトにコピーしました。 リソースとソースは「余分な」ものを排除しました。 次に、 GestureBuilderActivityクラスを変更して、指定されたジェスチャ(/ sdcard /ジェスチャではない)を開くようにしました。 そして、追加、削除、名前変更の機能を備えた言語のリストを作成しました。
結果
結果として生じる「キーボード」は、筆跡ではそれほど認識されませんが、継続的に使用しませんでした。キーは私にとってより便利です。 すべてのソースはgooglecode.comで表示できます。 Ibidは、英語、ロシア語、およびデジタルが組み込まれたAPKをダウンロードします(手書き用)。