onTouchEvent で「タッチアップ」を受信するとキーボードをポップアップするサブクラス化された View があります。フォーカスを要求し、InputMethodManager を取得して、showSoftInput を呼び出すことでこれを表示します。
ソフトキーボードのタップされた文字をキャプチャする方法を考えなければなりません。押されると現在は、ソフト キーボードの [次へ/完了] ボタンが押されたときにのみ応答があります。
私のクラスは次のとおりです。
public class BigGrid extends View {
private static final String TAG = "BigGrid";
public BigGrid(Context context) {
super(context);
setFocusableInTouchMode(true); // allows the keyboard to pop up on
// touch down
setOnKeyListener(new OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
Log.d(TAG, "onKeyListener");
if (event.getAction() == KeyEvent.ACTION_DOWN) {
// Perform action on key press
Log.d(TAG, "ACTION_DOWN");
return true;
}
return false;
}
});
}
@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
Log.d(TAG, "onTOUCH");
if (event.getAction() == MotionEvent.ACTION_UP) {
// show the keyboard so we can enter text
InputMethodManager imm = (InputMethodManager) getContext()
.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(this, InputMethodManager.SHOW_FORCED);
}
return true;
}
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
Log.d(TAG, "onCreateInputConnection");
BaseInputConnection fic = new BaseInputConnection(this, true);
outAttrs.actionLabel = null;
outAttrs.inputType = InputType.TYPE_CLASS_TEXT;
outAttrs.imeOptions = EditorInfo.IME_ACTION_NEXT;
return fic;
}
@Override
public boolean onCheckIsTextEditor() {
Log.d(TAG, "onCheckIsTextEditor");
return true;
}
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(R.color.grid_bg);
// .
// .
// alot more drawing code...
// .
}
}
キーボードは表示されますが、onKeyListener はキーボードの「次へ」ボタンを押したときにのみ起動します。onDraw() メソッドで表示できるように、どの文字がタップされたかを知る必要があります。
ベストアンサー1
実際には、TextView からビューを派生させずに、キー イベントを自分で処理することも可能です。
これを行うには、元のコードを次のように変更するだけです。
1) 次の行を置き換えますonCreateInputConnection():
outAttrs.inputType = InputType.TYPE_CLASS_TEXT;
これと一緒に:
outAttrs.inputType = InputType.TYPE_NULL;
ドキュメントによると、InputType.TYPE_NULL:
「これは、ターゲットの入力接続がリッチではなく、候補テキストなどを処理して表示したり、現在のテキストを取得したりできないため、入力メソッドを制限された「キーイベントの生成」モードで実行する必要があることを意味すると解釈する必要があります。」
2) 同じメソッドで次の行を置き換えます。
BaseInputConnection fic = new BaseInputConnection(this, true);
これと一緒に:
BaseInputConnection fic = new BaseInputConnection(this, false);
2番目の引数がfalseの場合、BaseInputConnectionは「ダミー」モードになり、また生のキー イベントをビューに送信するために必要です。BaseInputConnection コードには、次のようなコメントがいくつかあります。「ダミー モードの場合のみ、新しいテキストのキー イベントが送信され、現在の編集可能なバッファーがクリアされます。」
私はこのアプローチを使用して、ソフト キーボードが LinearLayout から派生したビュー (つまり、TextView から派生していないビュー) に生のイベントを送信するようにし、それが機能することを確認できました。
もちろん、IME_ACTION_DONE
キーボードに [完了] ボタンを表示するために imeOptions 値を設定する必要がない場合は、オーバーライドを完全に削除するだけで済みます。その場合、onCreateInputConnection()
よりonCheckIsTextEditor()
高度な処理が可能な入力接続が定義されていないため、生のイベントがデフォルトでビューに送信されます。
しかし残念ながら、これらのメソッドをオーバーライドして BaseInputConnection オブジェクトを提供せずに EditorInfo 属性を構成する簡単な方法はないようです。また、これを実行した後で、生のキー イベントを再度受信したい場合は、上記のようにそのオブジェクトによって実行される処理を簡素化する必要があります。
警告: Android に付属するデフォルトの LatinIME キーボード (Google キーボード) の最近の特定のバージョンに 2 つのバグが導入され、そのキーボードの使用時にキーボード イベント処理 (上記で説明したとおり) に影響を与える可能性があります。私はサンプル コードを使用して、これらの問題を回避できると思われるアプリ側での回避策をいくつか考案しました。これらの回避策を確認するには、次の回答を参照してください。