studio Feche/oculte o teclado virtual do Android




ocultar teclado android developer (24)

Eu tenho um EditText e um Button no meu layout.

Depois de escrever no campo de edição e clicar no Button , quero ocultar o teclado virtual. Eu suponho que este é um simples pedaço de código, mas onde posso encontrar um exemplo disso?


Simples e fácil de usar método, basta chamar hideKeyboardFrom (YourActivity.this); esconder o teclado

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

As respostas acima funcionam para cenários diferentes, mas se você quiser ocultar o teclado dentro de uma visualização e se esforçar para obter o contexto correto, tente o seguinte:

setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        hideSoftKeyBoardOnTabClicked(v);
    }
}

private void hideSoftKeyBoardOnTabClicked(View v) {
    if (v != null && context != null) {
        InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(v.getApplicationWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
    }
}

e para obter o contexto buscá-lo do construtor :)

public View/RelativeLayout/so and so (Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    this.context = context;
    init();
}

A resposta curta

Em seu ouvinte OnClick chame o onEditorAction do IME_ACTION_DONE com IME_ACTION_DONE

button.setOnClickListener(new OnClickListener() {

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

O drill-down

Eu sinto que este método é melhor, mais simples e mais alinhado com o padrão de design do Android. No exemplo simples acima (e geralmente na maioria dos casos comuns) você terá um EditText que tem / teve foco e também costumava ser o único a invocar o teclado em primeiro lugar (é definitivamente capaz de invocá-lo em muitos cenários comuns). Da mesma forma, deve ser o único a liberar o teclado, geralmente isso pode ser feito por um ImeAction . Basta ver como um EditText com android:imeOptions="actionDone" se comporta, você deseja obter o mesmo comportamento da mesma maneira.

Confira esta resposta relacionada


Graças a esta resposta , eu deduzi o seguinte que, no meu caso, funciona muito bem ao percorrer os fragmentos de um 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);
    }
}

Estou usando um teclado personalizado para inserir um número hexadecimal, portanto não posso exibir o teclado do IMM ...

Na v3.2.4_r1 setSoftInputShownOnFocus(boolean show) foi adicionado para controlar o tempo ou não para exibir o teclado quando um TextView obtém o foco, mas o seu ainda oculto para reflexão deve ser usado:

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

Para versões mais antigas, obtive resultados muito bons (mas longe de perfeitos) com um OnGlobalLayoutListener , adicionado com o auxílio de um ViewTreeObserver da minha visualização de raiz e, em seguida, verificando se o teclado é mostrado assim:

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

Essa última solução pode mostrar o teclado por uma fração de segundo e mexer com as alças de seleção.

Quando no teclado entra em tela cheia, onGlobalLayout não é chamado. Para evitar isso, use TextView#setImeOptions(int) ou na declaração TextView XML:

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

Atualização: Acabou de descobrir o que os diálogos usam para nunca mostrar o teclado e funciona em todas as versões:

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

Por favor, tente este código abaixo em onCreate()

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

Se todas as outras respostas aqui não funcionarem para você como você gostaria, existe outra maneira de controlar manualmente o teclado.

Crie uma função com a qual irá gerenciar algumas das propriedades do EditText :

public void setEditTextFocus(boolean isFocused) {
    searchEditText.setCursorVisible(isFocused);
    searchEditText.setFocusable(isFocused);
    searchEditText.setFocusableInTouchMode(isFocused);

    if (isFocused) {
        searchEditText.requestFocus();
    }
}

Então, certifique-se de que onFocus do EditText você abre / fecha o teclado:

searchEditText.setOnFocusChangeListener(new OnFocusChangeListener() {
    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        if (v == searchEditText) {
            if (hasFocus) {
                // Open keyboard
                ((InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE)).showSoftInput(searchEditText, InputMethodManager.SHOW_FORCED);
            } else {
                // Close keyboard
                ((InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(searchEditText.getWindowToken(), 0);
            }
        }
    }
});

Agora, sempre que você quiser abrir o teclado, ligue manualmente:

setEditTextFocus(true);

E para o fechamento da chamada:

setEditTextFocus(false);

Como alternativa a essa solução completa , se você quiser fechar o teclado virtual de qualquer lugar sem ter uma referência ao campo (EditText) que foi usado para abrir o teclado, mas ainda assim quiser fazê-lo se o campo estivesse focado, você poderia usar isso (de uma atividade):

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

Em alguns casos, esses métodos podem funcionar, exceto todos os outros. Isso salva meu dia :)

public static void hideSoftKeyboard(Activity activity) {
    if (activity != null) {
        InputMethodManager inputManager = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
        if (activity.getCurrentFocus() != null && inputManager != null) {
            inputManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0);
            inputManager.hideSoftInputFromInputMethod(activity.getCurrentFocus().getWindowToken(), 0);
        }
    }
}

public static void hideSoftKeyboard(View view) {
    if (view != null) {
        InputMethodManager inputManager = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
        if (inputManager != null) {
            inputManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
        }
    }
}

de tão pesquisando, aqui encontrei uma resposta que funciona para mim

// Show soft-keyboard:
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);

// Hide soft-keyboard:
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);

Eu tenho mais uma solução para esconder o teclado:

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

Aqui passe HIDE_IMPLICIT_ONLY na posição de showFlag e 0 na posição de hiddenFlag . Ele irá fechar com força o teclado suave.


Basta usar este código otimizado em sua atividade:

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

Eu tenho o caso, onde o meu também EditTextpode ser localizado em um AlertDialog, então o teclado deve ser fechado ao ser dispensado. O código a seguir parece estar funcionando em qualquer lugar:

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

Se você quiser fechar o teclado virtual durante uma unidade ou um teste funcional, você pode fazer isso clicando no botão "voltar" do seu teste:

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

Eu coloquei "botão de volta" entre aspas, uma vez que o acima não aciona o onBackPressed()para a atividade em questão. Apenas fecha o teclado.

Certifique-se de fazer uma pausa por um tempo antes de prosseguir, pois demora um pouco para fechar o botão Voltar, para que os cliques subsequentes para Visualizações, etc., não sejam registrados até uma pequena pausa (1 segundo é tempo suficiente) ).


Isso deve funcionar:

public class KeyBoard {

    public static void show(Activity activity){
        InputMethodManager imm = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
        imm.toggleSoftInput(0, InputMethodManager.HIDE_IMPLICIT_ONLY); // show
    }

    public static void hide(Activity activity){
        InputMethodManager imm = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
        imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0); // hide
    }

    public static void toggle(Activity activity){
        InputMethodManager imm = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
        if (imm.isActive()){
            hide(activity); 
        } else {
            show(activity); 
        }
    }
}

KeyBoard.toggle(activity);

Adicione à sua atividade android:windowSoftInputMode="stateHidden"no arquivo de manifesto. Exemplo:

<activity
            android:name=".ui.activity.MainActivity"
            android:label="@string/mainactivity"
            android:windowSoftInputMode="stateHidden"/>

usa isto

this.getWindow().setSoftInputMode(
            WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);

A solução de Meier também funciona para mim. No meu caso, o nível superior do meu aplicativo é um tabHost e eu quero esconder a palavra-chave ao alternar as guias - eu recebo o token da janela do tabHost View.

tabHost.setOnTabChangedListener(new OnTabChangeListener() {
    public void onTabChanged(String tabId) {
        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(tabHost.getApplicationWindowToken(), 0);
    }
}

Você pode forçar o Android a ocultar o teclado virtual usando o InputMethodManager , chamando hideSoftInputFromWindow , passando o token da janela que contém a visualização em foco.

// Check if no view has focus:
View view = this.getCurrentFocus();
if (view != null) {  
    InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}

Isso forçará o teclado a ficar oculto em todas as situações. Em alguns casos, você desejará passar InputMethodManager.HIDE_IMPLICIT_ONLY como o segundo parâmetro para garantir que você apenas oculte o teclado quando o usuário não forçar explicitamente a exibição (mantendo pressionado o menu).

Nota: Se você quiser fazer isso no Kotlin, use: context?.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager


Saurabh Pareek tem a melhor resposta até agora.

Pode também usar os sinalizadores corretos, no entanto.

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

Exemplo de uso real

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

Eu quase tentei todas essas respostas, eu tive alguns problemas aleatórios, especialmente com o samsung galaxy s5.

O que eu acabo forçando o show e se esconder, e funciona perfeitamente:

/**
 * Force show softKeyboard.
 */
public static void forceShow(@NonNull Context context) {
    InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
}

/**
 * Force hide softKeyboard.
 */
public static void forceHide(@NonNull Activity activity, @NonNull EditText editText) {
    if (activity.getCurrentFocus() == null || !(activity.getCurrentFocus() instanceof EditText)) {
        editText.requestFocus();
    }
    InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);
    activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
}

Para ajudar a esclarecer essa loucura, eu gostaria de começar pedindo desculpas em nome de todos os usuários do Android pelo tratamento absolutamente ridículo do Google para o teclado virtual. A razão pela qual existem tantas respostas, cada uma diferente, para a mesma pergunta simples é porque essa API, como muitas outras no Android, é horrivelmente projetada. Não consigo pensar em nenhum jeito educado de declarar isso.

Eu quero esconder o teclado. Espero fornecer ao Android a seguinte declaração: Keyboard.hide() . O fim. Muito obrigado. Mas o Android tem um problema. Você deve usar o InputMethodManager para ocultar o teclado. OK, esta é a API do Android para o teclado. MAS! Você é obrigado a ter um Context para obter acesso ao IMM. Agora nós temos um problema. Talvez eu queira ocultar o teclado de uma classe estática ou de utilitário que não tenha uso ou necessidade de nenhum Context . ou E pior ainda, o IMM exige que você especifique qual View (ou, pior ainda, qual Window ) deseja ocultar o teclado FROM.

É isso que faz com que esconder o teclado seja um desafio. Prezado Google: Quando estou procurando a receita de um bolo, não há RecipeProvider na Terra que se recusaria a me fornecer a receita, a menos que eu primeiro responda QUEM o bolo será comido por E onde será comido !!

Esta triste história termina com a verdade feia: para ocultar o teclado do Android, você deverá fornecer duas formas de identificação: um Context e uma View ou uma Window .

Eu criei um método de utilitário estático que pode fazer o trabalho muito solidamente, desde que você chamá-lo de uma 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);
}

Esteja ciente de que este método de utilidade só funciona quando chamado de uma Activity ! O método acima chama getCurrentFocus da Activity destino para buscar o token de janela apropriado.

Mas suponha que você deseja ocultar o teclado de um EditText hospedado em um DialogFragment ? Você não pode usar o método acima para isso:

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

Isso não funcionará porque você estará passando uma referência para a Activity host do Fragment , que não terá nenhum controle focalizado enquanto o Fragment é exibido! Uau! Então, por esconder o teclado dos fragmentos, eu recorro ao nível mais baixo, mais comum e mais feio:

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

Abaixo estão algumas informações adicionais coletadas de mais tempo desperdiçado em busca dessa solução:

Sobre windowSoftInputMode

Há ainda outro ponto de discórdia para estar ciente. Por padrão, o Android atribuirá automaticamente o foco inicial ao primeiro EditText ou controle focalizável em sua Activity . Segue naturalmente que o InputMethod (normalmente o teclado virtual) responderá ao evento de foco, mostrando-se. O atributo windowSoftInputMode no AndroidManifest.xml , quando definido como stateAlwaysHidden , instrui o teclado a ignorar esse foco inicial atribuído automaticamente.

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

Quase inacreditavelmente, parece não fazer nada para impedir que o teclado se abra quando você toca no controle (a menos que seja possível atribuir focusable="false" e / ou focusableInTouchMode="false" ao controle). Aparentemente, a configuração windowSoftInputMode se aplica apenas a eventos de foco automático, não para concentrar eventos acionados a partir de eventos de toque.

Portanto, stateAlwaysHidden é muito mal nomeado de fato. Talvez deva ser chamado de ignoreInitialFocus .

Espero que isto ajude.

ATUALIZAÇÃO: mais maneiras de obter um token de janela

Se não houver uma visualização focada (por exemplo, pode acontecer se você acabou de alterar fragmentos), há outras visualizações que fornecerão um token de janela útil.

Estas são alternativas para o código acima if (view == null) view = new View(activity); Estes não se referem explicitamente à sua atividade.

Dentro de uma classe de fragmentos:

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

Dado um fragmento de fragment como um parâmetro:

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

Começando pelo seu corpo de conteúdo:

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

ATUALIZAÇÃO 2: Limpar o foco para evitar a exibição do teclado novamente se você abrir o aplicativo a partir do plano de fundo

Adicione esta linha ao final do método:

view.clearFocus();


public void setKeyboardVisibility(boolean show) {
    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    if(show){
        imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
    }else{
        imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(),0);
    }
}

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




soft-keyboard