Fechar / ocultar o teclado virtual android

3819

Eu tenho um EditTexte um Buttonno meu layout.

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

Ao tocar fora do teclado.

Ak23
fonte
13
E se você tiver apenas um EditText e vários botões, como caixas de seleção e rádios? O único local em que você precisa do teclado é no único EditText. Como você se registra para saber que outra coisa foi escolhida / clicada para ocultar o teclado?
AlikElzin-kilaka
14
eu me sinto estúpido. Não consigo ocultar o teclado no ICS. Tentei todos os métodos aqui e combinações deles. De jeito nenhum. O método para mostrá-lo funciona, mas eu não posso ocultá-lo, independentemente do símbolo, das bandeiras, das manifestações ou das velas dos santos. No show do teclado, sempre vejo isso: I / LatinIME (396): InputType.TYPE_NULL é especificado W / LatinIME (396): Classe de entrada inesperada: inputType = 0x00000000 imeOptions = 0x00000000
rompe
4
/ ** * Este método é usado para ocultar o teclado virtual. * atividade @param * / public void hideSoftKeyboard (atividade Activity) {InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService (Activity.INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow (activity.getCurrentFocus (). getWindowToken (), 0); }
Harshal Benake
isso funcionou para mim
nmxprime
Com os dispositivos aumentando o tamanho e a resolução da tela, a ocultação do teclado virtual está se tornando menos importante.
Al-Kathiri Khalid

Respostas:

2038

Para ajudar a esclarecer essa loucura, gostaria de começar pedindo desculpas, em nome de todos os usuários do Android, pelo tratamento ridículo do Google com 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 nenhuma maneira educada de dizer isso.

Eu quero esconder o teclado. Espero para fornecer Android com a seguinte declaração: Keyboard.hide(). O fim. Muito obrigado. Mas o Android tem um problema. Você deve usar o InputMethodManagerpara ocultar o teclado. OK, tudo bem, esta é a API do Android para o teclado. MAS! Você precisa ter um Contextpara 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 utilidade ou necessidade Context. ou E Pior ainda, o IMM exige que você especifique o que View(ou pior, o que Window) deseja ocultar do teclado.

É isso que torna a ocultação do teclado um desafio. Caro Google: Quando estou pesquisando a receita de um bolo, não há RecipeProviderna Terra que se recusaria a me fornecer a receita, a menos que eu responda primeiro a QUEM o bolo será comido E onde será comido !!

Essa triste história termina com a feia verdade: para ocultar o teclado do Android, você precisará fornecer duas formas de identificação: Contextae a Viewou a ou a Window.

Eu criei um método de utilitário estático que pode fazer o trabalho MUITO solidamente, desde que você o chame de 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 utilitário só funciona quando chamado de um Activity! O método acima chama getCurrentFocuso destino Activitypara buscar o token de janela apropriado.

Mas suponha que você queira ocultar o teclado de um EditTexthost 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ê passará uma referência ao Fragmenthost do Activityque não terá controle focado enquanto o Fragmenté mostrado! Uau! Portanto, para ocultar fragmentos do teclado, recorro ao nível inferior, 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 obtidas com mais tempo desperdiçado na busca desta solução:

Sobre windowSoftInputMode

Há ainda outro ponto de discórdia a ter em conta. Por padrão, o Android atribui automaticamente o foco inicial ao primeiro EditTextou controle focalizável no seu Activity. Segue-se naturalmente que o InputMethod (normalmente o teclado virtual) responderá ao evento de foco, mostrando-se. O windowSoftInputModeatributo em 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 a abertura do teclado quando você toca no controle (a menos que focusable="false"e / ou focusableInTouchMode="false"esteja atribuído ao controle). Aparentemente, a configuração windowSoftInputMode se aplica apenas a eventos de foco automático, não a eventos de foco acionados por eventos de toque.

Portanto, stateAlwaysHiddené MUITO mal nomeado de fato. Talvez devesse ser chamado em seu ignoreInitialFocuslugar.

Espero que isto ajude.


UPDATE: Mais maneiras de obter um token de janela

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

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

Dentro de uma classe de fragmento:

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

Dado um fragmento fragmentcomo parâmetro:

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

A partir do seu corpo de conteúdo:

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

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

Adicione esta linha ao final do método:

view.clearFocus();

rmirabelle
fonte
2
Muito bom artigo. Uma coisa, no entanto, se você iniciar outra atividade em cima dela, que aciona o teclado, o teclado ainda estará presente quando você retornar. Corrigido isso removendo o teclado usando seu método ao sair da atividade principal.
Oyvind
3
@rmirabelle Em um Fragmentparece que você pode usargetActivity().getWindow().getDecorView()
McX
1
Este post é ótimo, mas você não tem duas partes muito importantes. As mudanças sutis feitas por versão e por manufatura. Por exemplo, em uma galáxia Samsung S6 precisamos usar .clearFocus () antes de esconder o teclado ... se não o teclado ainda irá aparecer no segundo clique de EditText: S
Warpzit
17
Google deve apenas realmente prever que Keyboard.hide();utilidade
HendraWD
1
[someView] .getContext () << Pode ser o caso da atividade. É o mesmo objeto sempre. (Exceto dentro de serviços ...)
Oliver Dixon
4419

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

// 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_ONLYcomo o segundo parâmetro para garantir que você oculte apenas o teclado quando o usuário não forçar explicitamente a aparecer (pressionando o menu).

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

Sintaxe de Kotlin

// Check if no view has focus:
 val view = this.currentFocus
 view?.let { v ->
  val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager 
  imm?.hideSoftInputFromWindow(v.windowToken, 0)
 }
Reto Meier
fonte
14
Graças, isso parece funcionar muito bem se usar 0 como o segundo parâmetro. Mas se eu usar o InputMethodManager.HIDE_IMPLICIT_ONLY, o teclado nunca ficará oculto (embora eu não esteja pressionando o menu). Alguma dica?
RoflcoptrException
27
Legal. Só para esclarecer, isso apenas a dispensa se presente, mas não impede que ela apareça, certo?
Cheezmeister 16/02
15
Pode ser proveitosamente para chamar editText.clearFocus () antes de esconder o softInput
user2224350
111
Chamando editText.clearFocus()em seguida, InputMethodManager.HIDE_IMPLICIT_ONLYfunciona até mesmo no4.1
sprocket12
11
O que funcionou para mim no 4.4 / htc foi executar View focused = getCurrentFocus()para obter o que é definitivamente a visão atualmente focada, chamando focused.clearFocus()e depois inputMethodManager.hideSoftInputFromWindow(focused.getWindowToken(), 0)(com sinalizadores claros).
Ionoclast Brigham
806

Também útil para ocultar o teclado virtual é:

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

Isso pode ser usado para suprimir o teclado virtual até que o usuário realmente toque na visualização EditText.

Garnet Ulrich
fonte
116
Você também pode obter o mesmo efeito adicionando android: windowSoftInputMode = "stateHidden" em sua atividade no manifesto.
CA
7
Tentei isso em um fragmento (referenciando a atividade proprietária) no nível 9 da API e, infelizmente, não funcionou. Tentei chamar onResume e onActivityCreated - sem efeito.
AgentKnopf
2
Estou trabalhando em um diálogo e isso funcionou. Estou usando o Android 3.2. Eu coloquei no método onCreateDialog (Bundle). Não funcionou no método onCreate. Caixa de diálogo = super.onCreateDialog (savedInstanceState); dialog.getWindow (). setSoftInputMode (WindowManager.LayoutParams. SOFT_INPUT_STATE_ALWAYS_HIDDEN); O resultado é que minha visão com EditTexts aparece sem o teclado. Quando o usuário toca em um texto de edição, o teclado é exibido.
Flobacca
4
Isso não funciona quando o foco ainda está em um EditText (como depois de tocar em um botão). Use a solução da Reto para isso.
Noumenon
4
Por que substituir configurações de manifesto é uma má idéia? Estou chamando isso de um fragmento. Não existe nenhuma definição manifesto que se aplica a um fragmento ...
Greg Ennis
349

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

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

Aqui passe HIDE_IMPLICIT_ONLYna posição de showFlage 0na posição de hiddenFlag. Ele fechará com força o teclado virtual.

Saurabh Pareek
fonte
4
Você está usando um sinalizador de ocultar no parâmetro showflags. Isso funciona apenas porque as constantes usam os mesmos números inteiros. Exemplo usando os sinalizadores corretos
Alex
testado em Android 4.0, eu gosto desta solução, porque eu tenho vários textos de edição, botões em que a atividade, que podem ter foco
32
@ Marcos: Porque o método é chamado de "toggleSoftInput", não "hideSoftInput" :)
Sver
19
Esta solução mostra o teclado se estiver oculto. Não é correto
Michael Katkov
1
@AkashAggarwal - "Funciona" se você ignorar o fato de que só funcionou para você porque o teclado estava aparecendo. (Alterna a visibilidade do teclado: oculta quando está sendo exibido, mas mostra quando está oculto !!) Você pode GARANTIR que, em todas as circunstâncias, em todos os dispositivos, para todas as versões futuras do Android, o teclado NÃO será mostrando no momento em que você chama isso? Se assim for, então vá em frente e use-o!
Home
149

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

tabHost.setOnTabChangedListener(new OnTabChangeListener() {
    public void onTabChanged(String tabId) {
        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(tabHost.getApplicationWindowToken(), 0);
    }
}
mckoss
fonte
Eu também trabalhei com o SearchView. Veja abaixo a minha resposta. Obrigado mckoss!
Azurespot
139

Tente este código abaixo em onCreate()

EditText edtView=(EditText)findViewById(R.id.editTextConvertValue);
edtView.setInputType(0);
Jeyavel
fonte
2
Esse método funciona como um meio de contornar o bug "não é possível ocultar o teclado virtual" nas versões 2.0 e 2.1, conforme descrito em code.google.com/p/android/issues/detail?id=7115 ... o método hideSoftInputFromWindow listado acima não funcionou quando tentei, mas editView.setInputType (0) funcionou.
Spike Williams
18
Esta é legítimo por Javadoc (não um hack) que eu iria reescrever o método comoeditView.setInputType(InputType.TYPE_NULL);
Bostone
3
isso funciona, no entanto, oculta o andróide: dica. Estou usando o Android 1.5
Tirtha
isso é ótimo para quando você precisa fechar o teclado em uma caixa de diálogo, não precisa obter uma instância nem nada e pode atribuir isso a todos os textos de edição quando o usuário pressiona um botão que fecha a caixa de diálogo
I'm_With_Stupid
Funciona, mas também está ocultando o cursor. Preciso do cursor, mas não do teclado do sistema.
Stefan Brendle
129

Atualização: não sei por que essa solução não funciona mais (acabei de testar no Android 23). Por favor, use a solução de Saurabh Pareek . Aqui está:

InputMethodManager imm = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
//Hide:
imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0);
//Show
imm.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0);

Resposta antiga:

//Show soft-keyboard:
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
//hide keyboard :
 getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
Nguyen Minh Binh
fonte
8
Onde devo colocar esse código? Eu tentei colar getWindow (). SetSoftInputMode (WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); no onCreate (), mas o teclado nunca está oculto #
user2236096
não trabalho, testado em radioGroup.setOnCheckedChangeListener, API 23
Christian Schäfer
Se você olhar mais de perto, InputMethodManager.HIDE_IMPLICIT_ONLY e InputMethodManager.SHOW_IMPLICIT têm o mesmo valor, que é "1", portanto não há diferença entre essas chamadas. => Não está funcionando
Palejandro
se estiver chamando imm.toggleSoftInput (InputMethodManager.HIDE_IMPLICIT_ONLY, 0); o teclado será exibido na tela :) A melhor implementação é: github.com/ravindu1024/android-keyboardlistener Shame no Android SDK
Duna
I don't know why this solution is not work any more- como é o Android , tudo será capaz de mudar, talvez em parte com um design ruim ... Escrevemos de forma descuidada, depois eliminamos tudo e reescrevemos tudo.
King King
89
protected void hideSoftKeyboard(EditText input) {
    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(input.getWindowToken(), 0);    
}
Sreedev R
fonte
5
Isso funcionou para mim! Mas por que você colocou input.setInputType (0) ? Não pude interagir com o EditTextView quando tive essa linha de código (funcionou quando o removi).
precisa saber é o seguinte
Provavelmente input.getContext().getSystemService(Context.INPUT_METHOD_SERVICE).
CoolMind 19/09/19
Eu removi input.setInputType(0);deste código. Ele mudou o comportamento do teclado e inputTypepara o EditText.
CoolMind #
74

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

Crie uma função que gerencie algumas das EditTextpropriedades de:

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

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

Em seguida, certifique-se de que, ao focar, EditTextabra / feche 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 manualmente, ligue para:

setEditTextFocus(true);

E para fechar a chamada:

setEditTextFocus(false);
Rotemmiz
fonte
+1 - Se você deseja iniciar uma atividade com teclado fechado, use esta solução e adicione um ouvinte onclicklist que define setEditTextFocus (true). Funciona como charme!
Schlingel
Eu recebi 'Não é possível resolver o contexto do símbolo', na 7ª e na 10ª linha do segundo bloco de código.
Gimmegimme
Use getContext () em vez disso
Rotemmiz 28/02
61

Saurabh Pareek tem a melhor resposta até agora.

No entanto, é melhor usar as bandeiras corretas.

/* 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 ... */
}
Alex
fonte
1
Este é o mais eficiente para a versão mais recente. Sempre será necessário ajustá-lo para versões mais antigas. Especialmente antes da v3.
25413 Alex
2
@Mazen: usefragment.getActivity().getSystemService();
Johan S
Esta é a resposta mais abrangente, cobrindo tanto mostrar quanto ocultar.
André Staltz
4
Não. Na minha guia Samsung, Android 5.0, o código de "ocultar teclado" acima alternará o teclado virtual - se ele já estiver oculto, será exibido. Há uma razão para essa função ter TOGGLE no nome.
Página Inicial>
57

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);
shontauro
fonte
O único que funcionou para mim para uma Motorola com Android 5.1
GMX 07/02
55

A resposta curta

No seu OnClickouvinte, chame o onEditorActionde EditTextcomIME_ACTION_DONE

button.setOnClickListener(new OnClickListener() {

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

O detalhamento

Eu sinto que esse 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 EditTextfoco que teve / teve e também foi o primeiro a invocar o teclado em primeiro lugar (é definitivamente capaz de invocá-lo em muitos cenários comuns). No mesmo caminho, ele deve ser o único a liberar o teclado, geralmente, que pode ser feito por um ImeAction. Basta ver como um EditTextcom android:imeOptions="actionDone"se comporta, você quer conseguir o mesmo comportamento pelos mesmos meios.


Verifique esta resposta relacionada

Alex.F
fonte
Esta é a resposta. Único método que funciona entre versões. Voltei para esta pergunta para postar esta resposta porque eu não acho que ninguém sabia
Noah Passalacqua
Essa deve ser a resposta correta. Em vez de enganar o Android para ocultar o teclado quando realmente deveria estar lá, dizemos que o usuário está pronto, o que, por sua vez, aciona o mesmo ImeAction [nome estúpido, admito] como se o usuário tivesse clicado em "CONCLUÍDO" no teclado . Dessa forma, não faz diferença se o usuário confirmar a entrada no teclado ou tocar no botão da interface do usuário.
Oliver Hausler
46

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);
slinden77
fonte
Funcionou parcialmente, mesmo que o teclado estivesse oculto "isActive ()" retorna falso!
Xpto # 04/13
Claro que sim, deveria. Ou talvez eu não te entenda. De qualquer forma, você pode complementar a classe hide()e os show()métodos para ter mais controle sobre quando ela deve aparecer e quando não. Funciona para mim, eu fiz isso também :) Vou editar o exemplo
slinden77 5/05
@YoushaAleayoub sim, será. KeyBoard.toggle(fragment.getActivity())
slinden77
@ slinden77, lol, eu estou falando sobre a sua resposta ... não esta que você comentou. Portanto, essa resposta ainda NÃO funcionará.
Yousha Aleayoub
@YoushaAleayoub uhm sim, será. A pergunta original não menciona fragmentos, foi você quem mencionou os fragmentos. Então, minha resposta é perfeitamente válida. Para usá-lo com fragmentos, chame o método de forma diferente de a Fragment, como um comentado. Aprenda a usar métodos, por favor, e depois volte. Você está confundindo as pessoas com suas respostas bobas
slinden77
43

Estou usando um teclado personalizado para inserir um número hexadecimal, para que o teclado IMM não seja exibido ...

Na v3.2.4_r1, setSoftInputShownOnFocus(boolean show)foi adicionado para controlar o clima ou não para exibir o teclado quando um TextView obtém o foco, mas ainda está oculto, portanto a reflexão deve ser usada:

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 serem perfeitos) com a OnGlobalLayoutListener, adicionados com a ajuda de a ViewTreeObserverda minha visualização raiz e 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);
    }
}

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

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

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

Atualização: Acabei de descobrir quais caixas de diálogo são usadas para nunca mostrar o teclado e funcionam em todas as versões:

getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
        WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
sergio91pt
fonte
Obrigado. Os dois sinalizadores FLAG_ALT_FOCUSABLE_IM e FLAG_ALT_FOCUSABLE_IM são atualmente a única coisa que ajudou no meu caso. Eu não queria que um teclado fosse exibido em minha atividade - nem mesmo quando o usuário clicou em um edittext. (Eu criei meu próprio "teclado").
18712 Daniel Novak
Solução legal, no entanto, se sua atividade frontal não estiver em tela cheia, o teclado estará visível por trás dele. Além disso, o auxílio ao movimento do cursor do teclado também é visível. E não é skinnable.
halxinate
Eu concordo. De todas as formas possíveis, apenas o método getWindow (). SetFlags () funciona, pelo menos no Android 5.1 em estoque. Observe que setSoftInputShownOnFocus () agora está setShowSoftInputOnFocus () e não está mais oculto, mas não funciona, pelo menos quando o usuário toca no campo.
olefevre
Sua "atualização" foi a única solução funcional para mim. Eu estou procurando uma solução pelo menos duas horas :)
Stefan BRENDLE
33
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);
    }
}
shobhan
fonte
30

Passei mais de dois dias trabalhando em todas as soluções postadas no segmento e as encontrei ausentes de uma maneira ou de outra. Meu requisito exato é ter um botão que mostre com 100% de confiabilidade ou oculte o teclado na tela. Quando o teclado está no estado oculto, ele não deve reaparecer, independentemente dos campos de entrada nos quais o usuário clica. Quando está no estado visível, o teclado não deve desaparecer, independentemente dos botões em que o usuário clica. Isso precisa funcionar no Android 2.2 ou superior até os dispositivos mais recentes.

Você pode ver uma implementação funcional disso no meu aplicativo, RPN limpo .

Depois de testar muitas das respostas sugeridas em vários telefones diferentes (incluindo dispositivos froyo e gingerbread), ficou claro que os aplicativos para Android podem:

  1. Ocultar temporariamente o teclado. Aparecerá novamente quando um usuário focalizar um novo campo de texto.
  2. Mostre o teclado quando uma atividade iniciar e defina um sinalizador na atividade, indicando que o teclado deve estar sempre visível. Este sinalizador só pode ser definido quando uma atividade está sendo inicializada.
  3. Marque uma atividade para nunca mostrar ou permitir o uso do teclado. Este sinalizador só pode ser definido quando uma atividade está sendo inicializada.

Para mim, ocultar temporariamente o teclado não é suficiente. Em alguns dispositivos, ele reaparece assim que um novo campo de texto é focado. Como meu aplicativo usa vários campos de texto em uma página, o foco em um novo campo de texto fará com que o teclado oculto volte a aparecer.

Infelizmente, os itens 2 e 3 da lista só funcionam com confiabilidade quando uma atividade está sendo iniciada. Depois que a atividade se tornar visível, você não poderá ocultar ou mostrar permanentemente o teclado. O truque é realmente reiniciar sua atividade quando o usuário pressionar o botão de alternância do teclado. No meu aplicativo, quando o usuário pressiona o botão de alternância do teclado, o seguinte código é executado:

private void toggleKeyboard(){

    if(keypadPager.getVisibility() == View.VISIBLE){
        Intent i = new Intent(this, MainActivity.class);
        i.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
        Bundle state = new Bundle();
        onSaveInstanceState(state);
        state.putBoolean(SHOW_KEYBOARD, true);
        i.putExtras(state);

        startActivity(i);
    }
    else{
        Intent i = new Intent(this, MainActivity.class);
        i.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
        Bundle state = new Bundle();
        onSaveInstanceState(state);
        state.putBoolean(SHOW_KEYBOARD, false);
        i.putExtras(state);

        startActivity(i);
    }
}

Isso faz com que a atividade atual tenha seu estado salvo em um pacote e, em seguida, a atividade é iniciada, passando por um booleano que indica se o teclado deve ser mostrado ou oculto.

Dentro do método onCreate, o seguinte código é executado:

if(bundle.getBoolean(SHOW_KEYBOARD)){
    ((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)).showSoftInput(newEquationText,0);
    getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
}
else{
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
            WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
}

Se o teclado virtual for mostrado, o InputMethodManager é instruído a mostrar o teclado e a janela é instruída a tornar a entrada virtual sempre visível. Se o teclado virtual estiver oculto, o WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM está definido.

Essa abordagem funciona de forma confiável em todos os dispositivos em que testei - de um telefone HTC de 4 anos com Android 2.2 até um nexus 7 com 4.2.2. A única desvantagem dessa abordagem é que você precisa ter cuidado ao manusear o botão Voltar. Como meu aplicativo basicamente possui apenas uma tela (é uma calculadora), posso substituir onBackPressed () e retornar à tela inicial do dispositivo.

Luke Sleeman
fonte
1
solução elaborada, mas acho que é demais, recriar milhares de objetos apenas para ocultar o teclado. Não sei quem projetou o IMM para o Android, mas cheira a um Windows APi. Na minha opinião, uma boa IME deve ter dois métodos: esconder e mostrar :-)
Rupps
É tudo verdade, mas minha solução alternativa tem uma vantagem - sempre funciona! Não há outra solução que eu possa encontrar que sempre alterne o teclado, independentemente de quais campos da interface do usuário tenham o foco, o que o usuário fez para alternar e o teclado e qual versão do android eles estão executando: - \
Luke Sleeman
Cara, estou totalmente desesperada para esconder o teclado. Tentei milhares de coisas e ninguém funciona. Mas sua solução alternativa é demais para mim, eu teria que recriar 10 fragmentos, inicializar serviços, excluir muitas WeakReferences ... você sabe? o GC apenas jogaria fora como 25mb: S ... Ainda procurando uma maneira confiável de fazê-lo :(
rompe
@ Dmitry bem, não é um olá mundo ... é um aplicativo complexo para tablets. Eu me recuso a descarregá-lo totalmente da memória apenas para esconder um teclado bobo ... De qualquer forma eu encontrei algo que funciona combinando os mil soluções propostas aqui :)
Rupps
27

Como alternativa a essa solução geral , se você deseja fechar o teclado virtual de qualquer lugar sem ter uma referência ao campo (EditText) usado para abrir o teclado, mas ainda assim deseja fazê-lo se o campo estiver focado, você poderá usar this (de uma atividade):

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

Graças a esta resposta do SO , deduzi o seguinte que, no meu caso, funciona bem ao rolar pelos 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);
    }
}
proibição de geoengenharia
fonte
21

As respostas acima funcionam para cenários diferentes, mas se você deseja ocultar o teclado dentro de uma visualização e se esforçando para obter o contexto certo, 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, busque-o no construtor :)

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

Se você deseja fechar o teclado virtual durante uma unidade ou teste funcional, clique no "botão voltar" do seu teste:

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

Coloquei o "botão voltar" entre aspas, pois o acima não aciona o onBackPressed()da Atividade em questão. Apenas fecha o teclado.

Faça uma pausa por um tempo antes de prosseguir, pois leva um pouco para fechar o botão Voltar, para que cliques subsequentes em Visualizações, etc., não sejam registrados até depois de uma breve pausa (1 segundo é o suficiente) )

Peter Ajtai
fonte
16

Veja como fazer isso no Mono para Android (AKA MonoDroid)

InputMethodManager imm = GetSystemService (Context.InputMethodService) as InputMethodManager;
if (imm != null)
    imm.HideSoftInputFromWindow (searchbox.WindowToken , 0);
Ian Vink
fonte
1
O que há searchboxno snippet?
PCoder
16

Isso funcionou para mim em todo o comportamento bizarro do teclado

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);
    }
}
Pinhassi
fonte
1
Acho que tentei 10 respostas antes desta. Tinha perdido a esperança. Obrigado cara.
20276 Bolling
O que é o mRootView?
justdan0227
14

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

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

Método simples e fácil de usar, 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);
}
Namaded Ahmad
fonte
13

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);
}
Hamid FzM
fonte
Funciona bem. obrigado
Alif
12
public static void hideSoftKeyboard(Activity activity) {
    InputMethodManager inputMethodManager = (InputMethodManager)  activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
    inputMethodManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0);
}

após essa chamada no onTouchListener:

findViewById(android.R.id.content).setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        Utils.hideSoftKeyboard(activity);
        return false;
    }
});
Sagar Maiyad
fonte
Tente isso também - funcionou para mim: InputMethodManager imm = ((InputMethodManager) getSystemService (Activity.INPUT_METHOD_SERVICE)); Clique com o botão direito do mouse sobre o arquivo e clique em Executar como Administrador.
Zmicer
12

usa isto

this.getWindow().setSoftInputMode(
            WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
Atish Agrawal
fonte
12

Para o meu caso, eu estava usando o a SearchView na barra de ação. Depois que um usuário realiza uma pesquisa, o teclado é aberto novamente.

O uso do InputMethodManager não fechou o teclado. Eu tive que limpar o Focus e definir o foco da visualização de pesquisa como false:

mSearchView.clearFocus();
mSearchView.setFocusable(false);
tommy chheng
fonte
1
Muito esperto. Se o usuário desejar outra pesquisa, basta clicar em Pesquisar novamente.
23413 Alex
O SearchView não possui um clearFocus()nas páginas da API do Android; portanto, isso não funcionou para mim, mas outra solução funcionou (veja minha resposta abaixo).
Azurespot
@Noni A, stackoverflow.com/questions/7409288/…
Yousha Aleayoub
12

Eu tenho o caso, onde meu também EditTextpode ser localizado em um AlertDialog, portanto, o teclado deve ser fechado ao ser descartado. 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 );
}
injetado
fonte
1
Esta solução é melhor porque você não precisa controlar qual EditText passa como parâmetro para o método hideSoftInputFromWindow (). Funciona muito bem !!
Billyjoker 12/02
12

Eu quase tentei todas essas respostas, tive alguns problemas aleatórios, especialmente com o Samsung Galaxy S5.

Acabo forçando o show e me escondendo, 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);
}
ahmed_khan_89
fonte