前回は、IME を制御するメソッドを作成した。今回は、EditText にフォーカスがあるかないかで IME の表示を制御してみる。目標は、
- EditText がフォーカスを得ると IME が起動
- EditText 以外の箇所をタップすると IME が終了
という動作だ。
普通にコーディングしただけだと、EditText 以外の箇所をタップしても IME が消えないことがあったので、少し強引なコードを用意してみた。以下のコードは、Context と EditText を引数として渡すことを前提にしている。showInputMethodEditor や hideInputMethodEditor は、前回作成したメソッドだ。
public static void inputMethodEditorControl(final Context context, final View view) { // EditText をタップしたらフォーカスを持つようにする view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (!view.hasFocus()) { view.setFocusable(true); view.setFocusableInTouchMode(true); view.requestFocus(); } } }); // EditText のフォーカスの変化に応じて IME を制御 final View.OnFocusChangeListener listener = view .getOnFocusChangeListener(); view.setOnFocusChangeListener(new View.OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { // フォーカスを持ったら表示 if (hasFocus) { showInputMethodEditor(context, view); } // フォーカスを失ったら非表示に else { hideInputMethodEditor(context, view); } if (null != listener) { listener.onFocusChange(v, hasFocus); } } }); // EditText の上位の View がクリックされたら EditText のフォーカスを外す ViewParent parent = view.getParent(); while (parent instanceof View) { View v = (View) parent; v.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { for (final View view : views) { view.setFocusable(false); view.setFocusableInTouchMode(false); view.clearFocus(); } } }); parent = v.getParent(); } }
コードの内容は、コメントを追加して説明してみた。最後の「EditText の上位の View がクリックされたら EditText のフォーカスを外す」の処理は、EditText の上位の View をたどっていって、どれかがタップされたら EditText をフォーカスできないように変更している。ただ、こんな処理が本当に必要なのか疑問だ。わざわざ View の階層をたどって処理を追加していかなければならないとしたら、結構面倒だ。何か間違えているか、勘違いしているか・・・設定を忘れているような気がするが、とりあえず動いているので使ってみている(もっとも、実際のコードは少し違うが)。よい方法が見つかったら、「Android の EditText の IME を制御する(3)」で報告したい。