1. ホーム
  2. android

[解決済み] Androidのソフトキーボードをプログラムで閉じる/隠すにはどうすればよいですか?

2022-03-17 23:36:25

質問

私は EditTextButton をレイアウトしています。

編集フィールドに書き込んだ後、クリックすると Button キーボードの外側をタッチすると、仮想キーボードが表示されないようにしたいのですが。これは簡単なコードだと思いますが、どこに例があるのでしょうか?

どのように解決するのですか?

この狂気の沙汰を明らかにするために、まず、すべてのAndroidユーザーを代表して、Googleのソフトキーボードに対する実に馬鹿げた扱いについて謝罪したいと思います。同じ単純な質問に対して、これほど多くの異なる回答があるのは、Androidの他の多くのAPIと同様に、このAPIが恐ろしく設計されていることが原因です。ということです。

キーボードを隠したい。 私は、Androidに次のような記述を期待しています。 Keyboard.hide() . 終了です。ありがとうございました。 しかし、Androidには問題があります。 を使う必要があります。 InputMethodManager でキーボードを隠します。よしよし、これがAndroidのキーボードへのAPIだ。BUT!あなたは、キーボードを隠すために Context IMMにアクセスするために。さて、問題が発生しました。 キーボードを静的クラスやユーティリティクラスから隠したいのですが、そのクラスでは、IMMを使う必要がありません。 Context あるいは、もっと悪いことに、IMMは、あなたがどのような View (あるいはさらに悪いことに Window キーボードのFROMを隠したい場合。

これが、キーボードを隠すことの難しさです。Googleさんへ。ケーキのレシピを調べているときに RecipeProvider そのケーキを誰が食べるか、どこで食べるかを答えなければ、レシピの提供を拒否するようなことは、この地球上ではありえないのです。

この悲しい物語は、醜い真実で終わります。Androidキーボードを隠すには、次の2つの身分証明書の提出が必要です。 ContextView または Window .

この静的ユーティリティ・メソッドは、非常にしっかりとした仕事をすることができます。 Activity .

public static void hideKeyboard(Activity activity) {
    InputMethodManager imm = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
    //Find the currently focused view, so we can grab the correct window token from it.
    View view = activity.getCurrentFocus();
    //If no view currently has focus, create a new one, just so we can grab a window token from it
    if (view == null) {
        view = new View(activity);
    }
    imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}

このユーティリティ・メソッドは、以下のメソッドから呼び出されたときのみ機能することに注意してください。 Activity ! 上記のメソッドは getCurrentFocus ターゲット Activity を使用して、適切なウィンドウ トークンを取得します。

しかし、仮にキーボードを EditText でホストされている DialogFragment ? その場合、上記の方法は使えません。

hideKeyboard(getActivity()); //won't work

への参照を渡すことになるので、これはうまくいきません。 Fragment のホスト Activity を使用すると、フォーカスされた制御ができなくなります。 Fragment が表示されます! すげえええええええええええええええええええええええ というわけで、キーボードをフラグメントから隠すには、より低レベルで、より一般的で、より醜いものに頼ることにしました。

public static void hideKeyboardFrom(Context context, View view) {
    InputMethodManager imm = (InputMethodManager) context.getSystemService(Activity.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}

以下は、この解決策を追い求め、さらに時間を費やした結果得られた追加情報です。

windowSoftInputModeについて

さらにもうひとつ、注意しなければならない点があります。デフォルトでは、Android は最初のフォーカスを自動的に最初の EditText またはフォーカス可能なコントロールが Activity . 当然、InputMethod(通常はソフトキーボード)は自分自身を表示することでフォーカスイベントに応答することになります。そのため windowSoftInputMode 属性は AndroidManifest.xml に設定されている場合は stateAlwaysHidden は、この自動的に割り当てられた初期フォーカスを無視するようにキーボードに指示します。

<activity
    android:name=".MyActivity"
    android:windowSoftInputMode="stateAlwaysHidden"/>

ほとんど信じられないことですが、コントロールをタッチしたときにキーボードが開くのを防ぐことはできないようです(ただし focusable="false" および focusableInTouchMode="false" がコントロールに割り当てられている)。どうやら、windowSoftInputModeの設定は、自動フォーカスイベントのみに適用され、タッチイベントによって引き起こされるフォーカスイベントには適用されないようです。

そのため stateAlwaysHidden は、実にお粗末な名前である。おそらくこう呼ぶべきでしょう ignoreInitialFocus の代わりに


UPDATE: ウィンドウ トークンを取得するその他の方法

フォーカスされたビューがない場合 (たとえば、フラグメントを変更したばかりの場合)、有用なウィンドウ トークンを提供するビューが他にあります。

上記のコードに代わるものとして、以下のものがあります。 if (view == null) view = new View(activity); これらは、あなたの活動を明示的に参照しているわけではありません。

フラグメントクラスの内部。

view = getView().getRootView().getWindowToken();

フラグメントがある場合 fragment をパラメータとする。

view = fragment.getView().getRootView().getWindowToken();

コンテンツ本体からスタートします。

view = findViewById(android.R.id.content).getRootView().getWindowToken();


UPDATE 2: バックグラウンドからアプリを開いても再びキーボードが表示されないようにフォーカスをクリアにする

この行をメソッドの末尾に追加します。

view.clearFocus();