關閉/隱藏Android軟鍵盤


Answers

為了澄清這種瘋狂,我想首先代表所有Android用戶道歉,因為谷歌對軟鍵盤的徹底荒謬處理。 對於同樣簡單的問題,有很多答案各不相同,這是因為與Android中的其他許多API一樣,這個API的設計非常糟糕。 我可以想到沒有禮貌的方式來陳述它。

我想隱藏鍵盤。 我期望為Android提供以下語句: Keyboard.hide() 。 結束。 非常感謝你。 但Android有一個問題。 您必須使用InputMethodManager來隱藏鍵盤。 好的,很好,這是Android的鍵盤API。 但! 您需要有一個Context才能訪問IMM。 現在我們有一個問題。 我可能希望將鍵盤從靜態或實用程序類中隱藏起來,該類沒有任何用處或者不需要任何Context 。 或者更糟糕的是,IMM要求您指定要隱藏鍵盤FROM的View (甚至更糟,是哪個Window )。

這就是隱藏鍵盤如此具有挑戰性的原因。 親愛的Google:當我查找蛋糕的食譜時,地球上沒有RecipeProvider會拒絕為我提供配方,除非我第一次回答WHO蛋糕將被吃掉並且它將被吃掉!

這個令人傷心的故事以醜陋的真相結束:為了隱藏Android鍵盤,您將需要提供兩種識別形式: Context以及ViewWindow

我創建了一個靜態實用程序方法,只要您從一個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來獲取正確的窗口標記。

但是,假設你想隱藏在DialogFragment託管的EditText的鍵盤? 你不能使用上面的方法:

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或可聚焦控件。 自然地,InputMethod(通常是軟鍵盤)將通過顯示自己來響應焦點事件。 AndroidManifest.xmlwindowSoftInputMode屬性設置為stateAlwaysHidden ,會指示鍵盤忽略此自動分配的初始焦點。

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

幾乎令人難以置信的是,當您觸摸控件時(除非focusable="false"和/或focusableInTouchMode="false"分配給控件),它似乎無法阻止鍵盤打開。 顯然,windowSoftInputMode設置僅適用於自動焦點事件,而不是焦點觸摸事件觸發的事件。

因此, stateAlwaysHidden確實的命名非常糟糕。 它也許應該被稱為ignoreInitialFocus

希望這可以幫助。

更新:獲取窗口令牌的更多方法

如果沒有專注的視圖(例如,如果您只是更改了片段就會發生),還有其他視圖可以提供有用的窗口標記。

這些是上述代碼的替代方案, 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

我的佈局中有一個EditText和一個Button

在編輯欄中寫入並單擊Button ,我想要隱藏虛擬鍵盤。 我認為這是一段簡單的代碼,但我可以在哪裡找到它的一個例子?




我還有一個解決方案來隱藏鍵盤:

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

這裡在HIDE_IMPLICIT_ONLY的位置傳遞HIDE_IMPLICIT_ONLY ,在HIDE_IMPLICIT_ONLY的位置showFlag 0 。 它會強制關閉軟鍵盤。




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);
    }
}



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);
    }
}



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).




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 ... */
}



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



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);
}



我有這種情況,我的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 );
}



請在oncreate()中嘗試以下代碼

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




簡短的答案

在您的OnClick偵聽器中使用onEditorAction調用EditTextIME_ACTION_DONE

button.setOnClickListener(new OnClickListener() {

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

下鑽

我覺得這種方法更好,更簡單,更符合Android的設計模式。 在上面的簡單示例中(通常在大多數常見情況下),您將擁有一個具有/有焦點的EditText ,它通常也是首先調用鍵盤的EditText (它肯定能夠在其中調用它許多常見的情況)。 以同樣的方式, 應該是釋放鍵盤的那個,通常可以通過ImeAction來完成。 只要看看一個帶有android:imeOptions="actionDone"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);



除此之外,如果您想從任何地方關閉軟鍵盤而無需參考用於打開鍵盤的(EditText)字段,但仍想在字段集中時進行操作,則可以使用這個(來自一個Activity):

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



我正在使用自定義鍵盤輸入​​十六進制數字,因此我無法顯示IMM鍵盤...

在v3.2.4_r1中, setSoftInputShownOnFocus(boolean show)被添加來控制天氣,或者當TextView獲得焦點時不顯示鍵盤,但它仍然隱藏,因此必須使用反射:

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獲得了非常好的結果(但還遠沒有完美),並在我的根視圖中添加了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);
}



Related