前回は、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)」で報告したい。