Android 소프트 키보드 닫기 / 숨기기


Answers

이 광기를 명확히하기 위해, 나는 안드로이드 사용자를 대신해서 소프트 키보드에 대한 Google의 완전히 우스운 취급에 대해 사과하는 것으로 시작하고 싶습니다. 똑같은 질문에 대해 여러 가지 답변이 많이 존재하는 이유는 Android의 다른 많은 사람들처럼이 API가 끔찍하게 설계 되었기 때문입니다. 나는 그것을 정중하게 말할 방법이 없다고 생각할 수있다.

키보드를 숨기고 싶습니다. 안드로이드에게 Keyboard.hide() 문을 제공 할 것을 기대합니다. 끝. 고맙습니다. 하지만 안드로이드는 문제가있다. 키보드를 숨기려면 InputMethodManager 를 사용해야합니다. 좋아요. 안드로이드의 키보드 API입니다. 그러나! IMM에 액세스하려면 Context 가 있어야합니다. 이제 우리에게는 문제가 있습니다. 어떤 Context 를 사용하거나 필요로하지 않는 정적 또는 유틸리티 클래스에서 키보드를 숨길 수 있습니다. 또는 더 나쁜 것은, IMM은 키보드 FROM을 숨길 View (또는 더 나쁜, 어떤 Window )를 지정해야합니다.

이것이 키보드를 숨기는 것을 어렵게 만드는 이유입니다. 친애하는 구글 : 내가 케이크를위한 요리법을 찾고있을 때, 내가 먼저 케이크에 먹을 것 인 곳에 대답하지 않는 한, 요리법을 나에게 제공하기를 거부 할 지구상의 RecipeProvider 는 없다.

이 슬픈 이야기는 추악한 사실로 끝납니다. Android 키보드를 숨기려면 ContextView 또는 Window 두 가지 형태의 ID를 제공해야 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 를 호출하여 적절한 창 토큰을 가져옵니다.

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는 처음 포커스를 Activity 의 첫 번째 EditText 또는 포커스 가능 컨트롤에 자동으로 할당합니다. 자연스럽게 InputMethod (일반적으로 소프트 키보드)는 포커스 이벤트에 응답하여 응답합니다. AndroidManifest.xmlwindowSoftInputMode 속성이 windowSoftInputMode 설정되면 키보드에 자동으로 할당 된이 초기 포커스를 무시하도록 지시합니다.

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

업데이트 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 );
}



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



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



oncreate () 코드 아래에서 이것을 시도하십시오.

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




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



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



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



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



이 솔루션을 둘러싼 다른 방법과 달리, 키보드를 여는 데 사용 된 (EditText) 필드에 대한 참조없이 어디에서나 소프트 키보드를 닫으려고해도 필드가 포커스가있는 경우에도 계속하고 싶다면 다음을 사용할 수 있습니다. 이것은 (활동에서) :

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



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



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




짧은 대답

OnClick 수신기에서 onEditorAction 을 사용하여 EditTextonEditorAction 을 호출하십시오.

button.setOnClickListener(new OnClickListener() {

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

드릴 다운

이 방법이 Android의 디자인 패턴에 더 좋고, 더 간단하고, 정렬되어 있다고 느낍니다. 위의 간단한 예에서 (일반적으로 대부분의 일반적인 경우) 포커스가있는 / 편집 된 EditText 가 있으며 대개 처음부터 키보드를 호출하는 EditText 가 있습니다 (확실히 키보드를 호출 할 수 있습니다). 많은 일반적인 시나리오). 똑같은 방식으로 키보드를 ImeAction 합니다. 일반적으로 ImeAction 으로 수행 할 수 있습니다. android:imeOptions="actionDone" 이있는 EditText 가 어떻게 작동하는지보고, 똑같은 방식으로 동일한 동작을 원합니다.

관련 답변 확인




키보드를 숨길 수있는 솔루션이 하나 더 있습니다.

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

여기에서는 showFlag 의 위치에서 HIDE_IMPLICIT_ONLY 를 전달하고 HIDE_IMPLICIT_ONLY 의 위치에서 0hiddenFlag 합니다. 그것은 부드러운 키보드를 강제로 닫을 것입니다.




IMM 키보드를 표시 할 수 없도록 사용자 정의 키보드를 사용하여 16 진수를 입력하고 있습니다 ...

v3.2.4_r1에서는 날씨를 제어하거나 TextView에 포커스가있을 때 키보드를 표시하지 않도록 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 를 추가 한 다음 키보드가 다음과 같이 표시되는지 확인합니다.

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



Related