Androidソフトキーボードを閉じる/隠す


Answers

この狂気をはっきりさせるために、私はすべてのAndroidユーザーに代わって、ソフトキーボードのGoogleの間違った扱いに対する謝罪から始めたいと考えています。 同じ簡単な質問のために、それぞれが異なる、非常に多くの答えがある理由は、Androidの多くの他のユーザーと同様、このAPIもひどく設計されているためです。 私はそれを述べる礼儀正しい方法を考えることはできません。

私はキーボードを隠したい。 私はAndroidに次の文を提供することを期待しています: Keyboard.hide() 。 終わり。 どうもありがとうございました。 しかし、Androidには問題があります。 InputMethodManagerを使用してキーボードを非表示にする必要があります。 OK、これはAndroidのAndroid APIです。 しかし! IMMにアクセスするためには、 Contextが必要です。 今私たちには問題があります。 Context必要としない静的クラスまたはユーティリティクラスからキーボードを隠したい場合があります。 またはさらに悪いことに、IMMでは、キーボードからFROMを隠すView (またはさらに悪いWindow )を指定する必要があります。

これは、キーボードを隠すことを難しくする原因です。 親愛なるGoogle:私がケーキのレシピを見ているとき、私が最初にWHOに答えない限り、私にレシピを提供することを拒否するレシピRecipeProviderはありません。 RecipeProvider 、それはどこで食べられるのですか?

この悲しい話は醜い真実で終わります。Androidキーボードを隠すためには、2つの形式のID( 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から呼び出されたときにのみ機能することに注意してください。 上記のメソッドは、目的のActivity getCurrentFocusを呼び出して、適切なウィンドウトークンを取得します。

しかし、 EditTextホストされているDialogFragmentからキーボードを隠したいとします。 上記の方法を使用することはできません:

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

これは、 Fragmentが表示されている間は、フォーカスのコントロールを持たないFragmentのホストActivityへの参照を渡すため、機能しません! うわー! だから、キーボードを断片から隠すために、私はより低いレベルの、より一般的で醜い人に頼っています:

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またはフォーカス可能なコントロールに自動的に初期フォーカスを割り当てます。 当然のことながら、InputMethod(通常はソフトキーボード)は、フォーカスイベントにそれ自身を示すことによって応答します。 AndroidManifest.xmlwindowSoftInputMode属性( windowSoftInputModeに設定されているstateAlwaysHidden 、この自動的に割り当てられた初期フォーカスをキーボードが無視するように指示します。

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

ほぼ信じられないほど、コントロールに触れると( focusable="false"および/またはfocusableInTouchMode="false"がコントロールに割り当てられていない限り)キーボードが開いてしまうのを防ぐために何もしていないようです。 どうやら、windowSoftInputModeの設定は、自動フォーカスイベントにのみ適用され、タッチイベントからトリガされたイベントにはフォーカスが当てられません。

したがって、 stateAlwaysHiddenは実際には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();

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

この行をメソッドの最後に追加します。

view.clearFocus();

Question

レイアウトにEditTextButtonがあります。

編集フィールドに書き込んでButtonをクリックした後、仮想キーボードを非表示にしたい。 私はこれが単純なコードだと仮定しますが、どこでその例を見つけることができますか?




私はケースEditTextもあります。どこにでも私の場所を見つけることができるAlertDialogので、キーボードを閉じて閉じなければなりません。次のコードはどこでも動作しているようです:

public static void hideKeyboard( Activity activity ) {
    InputMethodManager imm = (InputMethodManager)activity.getSystemService( Context.INPUT_METHOD_SERVICE );
    View f = activity.getCurrentFocus();
    if( null != f && null != f.getWindowToken() && EditText.class.isAssignableFrom( f.getClass() ) )
        imm.hideSoftInputFromWindow( f.getWindowToken(), 0 );
    else 
        activity.getWindow().setSoftInputMode( WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN );
}



Simple and Easy to use method, just call hideKeyboardFrom(YourActivity.this); to hide keyboard

/**
 * This method is used to hide keyboard
 * @param activity
 */
public static void hideKeyboardFrom(Activity activity) {
    InputMethodManager imm = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0);
}



protected void hideSoftKeyboard(EditText input) {
    input.setInputType(0);
    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(input.getWindowToken(), 0);    
}



Saurabh Pareekはこれまで最高の答えを持っています。

しかし、適切なフラグを使用することもできます。

/* hide keyboard */
((InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE))
    .toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0);

/* show keyboard */
((InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE))
    .toggleSoftInput(0, InputMethodManager.HIDE_IMPLICIT_ONLY);

実際の使用例

/* click button */
public void onClick(View view) {      
  /* hide keyboard */
  ((InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE))
      .toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0);

  /* start loader to check parameters ... */
}

/* loader finished */
public void onLoadFinished(Loader<Object> loader, Object data) {
    /* parameters not valid ... */

    /* show keyboard */
    ((InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE))
        .toggleSoftInput(0, InputMethodManager.HIDE_IMPLICIT_ONLY);

    /* parameters valid ... */
}



私は16進数を入力するカスタムキーボードを使用しているので、私はIMMキーボードを表示することはできません...

v3.2.4_r1 setSoftInputShownOnFocus(boolean show) 、TextViewにフォーカスが当たったsetSoftInputShownOnFocus(boolean show)天気を制御するためにキーボードを表示しないようにsetSoftInputShownOnFocus(boolean show)が追加されましたが、まだ隠れているので反射を使用する必要があります:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
    try {
        Method method = TextView.class.getMethod("setSoftInputShownOnFocus", boolean.class);
        method.invoke(mEditText, false);
    } catch (Exception e) {
        // Fallback to the second method
    }
}

古いバージョンでは、 OnGlobalLayoutListener使って非常に良い結果が得られましたが(完璧ではありOnGlobalLayoutListener )、ルートビューのViewTreeObserver使って追加し、キーボードが次のように表示されているかどうかを確認します。

@Override
public void onGlobalLayout() {
    Configuration config = getResources().getConfiguration();

    // Dont allow the default keyboard to show up
    if (config.keyboardHidden != Configuration.KEYBOARDHIDDEN_YES) {
        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(mRootView.getWindowToken(), 0);
    }
}

この最後の解決策は、キーボードを分割して表示し、選択ハンドルを鳴らすことがあります。

キーボードのフルスクリーンに入ると、onGlobalLayoutは呼び出されません。 これを避けるには、 TextView#setImeOptions(int)使用するか、TextView XML宣言で使用します。

android:imeOptions="actionNone|actionUnspecified|flagNoFullscreen|flagNoExtractUi"

アップデート:ちょうどダイアログを使用してキーボードを表示しないようにし、すべてのバージョンで動作することを発見しました。

getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
        WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);



Just use this optimized code in your activity:

if (this.getCurrentFocus() != null) {
    InputMethodManager inputManager = (InputMethodManager) this.getSystemService(Context.INPUT_METHOD_SERVICE);
    inputManager.hideSoftInputFromWindow(this.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}



oncreate()で以下のコードを試してみてください。

EditText edtView =(EditText)findViewById(R.id.editTextConvertValue); edtView.setInputType(0);




If you want to close the soft keyboard during a unit or functional test, you can do so by clicking the "back button" from your test:

// Close the soft keyboard from a Test
getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);

I put "back button" in quotes, since the above doesn't trigger the onBackPressed() for the Activity in question. It just closes the keyboard.

Make sure to pause for a little while before moving on, since it takes a little while to close the back button, so subsequent clicks to Views, etc., won't be registered until after a short pause (1 second is long enough ime).




私はキーボードを隠すもう一つの解決策を得た:

InputMethodManager imm = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0);

ここでは、 showFlagの位置でshowFlagを渡し、 HIDE_IMPLICIT_ONLYの位置で0hiddenFlagます。 それは、ソフトキーボードを強制的に閉じます。




短い答え

OnClickリスナーで、 onEditorActionを使用してEditTextIME_ACTION_DONE

button.setOnClickListener(new OnClickListener() {

    @Override
    public void onClick(View v) {
        someEditText.onEditorAction(EditorInfo.IME_ACTION_DONE)
    }
});

ドリルダウン

私は、この方法がAndroidのデザインパターンによって、よりシンプルで、より整っていると感じています。 上記の単純な例(通常はほとんどの一般的な例)では、 EditTextを持っている/ EditTextしているEditTextを持っていて、通常はキーボードを最初に呼び出すものでした(これは間違いなく多くの一般的なシナリオ)。 同じように、 それはキーボードをリリースするものなければなりません。通常、これはImeActionで行うことができます。 android:imeOptions="actionDone" EditTextがどのようにEditTextするか見てみましょう。あなたは同じ手段で同じ振る舞いをしたいと思っています。

この関連する回答を確認してください




For my case, I was using the a SearchView in the actionbar. After a user performs a search, the keyboard would pop open again.

Using the InputMethodManager did not close the keyboard. I had to clearFocus and set the focusable of the search view to false:

mSearchView.clearFocus();
mSearchView.setFocusable(false);



Thanks to this SO answer , I derived the following which, in my case, works nicely when scrolling through the the fragments of a ViewPager...

private void hideKeyboard() {   
    // Check if no view has focus:
    View view = this.getCurrentFocus();
    if (view != null) {
        InputMethodManager inputManager = (InputMethodManager) this.getSystemService(Context.INPUT_METHOD_SERVICE);
        inputManager.hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
    }
}

private void showKeyboard() {   
    // Check if no view has focus:
    View view = this.getCurrentFocus();
    if (view != null) {
        InputMethodManager inputManager = (InputMethodManager) this.getSystemService(Context.INPUT_METHOD_SERVICE);
        inputManager.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT);
    }
}



これを全面的に解決する方法の代わりに、キーボードを開くために使用された(EditText)フィールドへの参照を使わずにどこからでもソフトキーボードを閉じるには、フィールドがフォーカスされていてもそれをやりたければ、これは(アクティビティから)

if (getCurrentFocus() != null) {
    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
}



This worked for me for all the bizarre keyboard behavior

private boolean isKeyboardVisible() {
    Rect r = new Rect();
    //r will be populated with the coordinates of your view that area still visible.
    mRootView.getWindowVisibleDisplayFrame(r);

    int heightDiff = mRootView.getRootView().getHeight() - (r.bottom - r.top);
    return heightDiff > 100; // if more than 100 pixels, its probably a keyboard...
}

protected void showKeyboard() {
    if (isKeyboardVisible())
        return;
    InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    if (getCurrentFocus() == null) {
        inputMethodManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
    } else {
        View view = getCurrentFocus();
        inputMethodManager.showSoftInput(view, InputMethodManager.SHOW_FORCED);
    }
}

protected void hideKeyboard() {
    if (!isKeyboardVisible())
        return;
    InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    View view = getCurrentFocus();
    if (view == null) {
        if (inputMethodManager.isAcceptingText())
            inputMethodManager.toggleSoftInput(InputMethodManager.HIDE_NOT_ALWAYS, 0);
    } else {
        if (view instanceof EditText)
            ((EditText) view).setText(((EditText) view).getText().toString()); // reset edit text bug on some keyboards bug
        inputMethodManager.hideSoftInputFromInputMethod(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
    }
}





Related