Ok, todo mundo sabe que, para ocultar um teclado, você precisa implementar:
InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
Mas o grande problema aqui é como ocultar o teclado quando o usuário toca ou seleciona qualquer outro lugar que não EditText
seja o ou o softKeyboard?
Tentei usar o onTouchEvent()
no meu pai, Activity
mas isso só funciona se o usuário tocar fora de qualquer outra visualização e não houver rolagem.
Tentei implementar um toque, clique, focalize o ouvinte sem sucesso.
Até tentei implementar minha própria visualização de rolagem para interceptar eventos de toque, mas só consigo obter as coordenadas do evento e não clicar na visualização.
Existe uma maneira padrão de fazer isso? no iPhone foi muito fácil.
android
android-softkeyboard
htafoya
fonte
fonte
getFields()
aqui: stackoverflow.com/questions/7790487/…Respostas:
O seguinte trecho simplesmente oculta o teclado:
Você pode colocar isso em uma classe de utilitário ou, se estiver definindo em uma atividade, evite o parâmetro de atividade ou chame
hideSoftKeyboard(this)
.A parte mais complicada é quando chamá-lo. Você pode escrever um método que itere em todas as
View
suas atividades e verificar se é uminstanceof EditText
se não estiver registrandosetOnTouchListener
a nesse componente e tudo se encaixará. Caso você esteja se perguntando como fazer isso, é de fato bastante simples. Aqui está o que você faz, você escreve um método recursivo como o seguinte, na verdade, você pode usá-lo para fazer qualquer coisa, como configurar tipos de letra personalizados etc ... Aqui está o métodoIsso é tudo, basta chamar esse método depois de você
setContentView
em sua atividade. Caso você esteja se perguntando qual parâmetro você passaria, é oid
do contêiner pai. Atribua umid
ao seu container pai como<RelativeLayoutPanel android:id="@+id/parent"> ... </RelativeLayout>
e ligar
setupUI(findViewById(R.id.parent))
, isso é tudo.Se você deseja usar isso efetivamente, poderá criar um
Activity
método estendido e colocar esse método, além de fazer com que todas as outras atividades em seu aplicativo estendam essa atividade e chamem-setupUI()
no noonCreate()
métodoEspero que ajude.
Se você usar mais de uma atividade, defina o ID comum para o layout pai, como
<RelativeLayout android:id="@+id/main_parent"> ... </RelativeLayout>
Em seguida, estenda uma classe
Activity
e definasetupUI(findViewById(R.id.main_parent))
Dentro delaOnResume()
e estenda essa classe em vez de `` Atividadein your program
Aqui está uma versão Kotlin da função acima:
fonte
if(activity.getCurrentFocus() != null) {...}
OnTouchListener
para elas. Você pode simplesmente definir essa lógica em umaViewGroup.onInterceptTouchEvent(MotionEvent)
para uma visualização raiz.Você pode conseguir isso executando as seguintes etapas:
Torne a visualização principal (visualização de conteúdo da sua atividade) clicável e focável, adicionando os seguintes atributos
Implementar um método hideKeyboard ()
Por fim, defina o onFocusChangeListener do seu edittext.
Conforme indicado em um dos comentários abaixo, isso pode não funcionar se a exibição pai for um ScrollView. Nesse caso, o Clickable e focusableInTouchMode podem ser adicionados à exibição diretamente sob o ScrollView.
fonte
clickable
efocusableInTouchMode
ao meuScrollView
elemento raiz . Eu tive que adicionar ao pai direto do meuEditText
que era umLinearLayout
.Basta substituir o código abaixo na Atividade
fonte
Acho a resposta aceita um pouco complicada.
Aqui está a minha solução. Adicione um
OnTouchListener
ao seu layout principal, ou seja:e coloque o seguinte código no método onTouch.
Dessa forma, você não precisa repetir todas as visualizações.
fonte
android:onClick="stealFocusFromEditTexts"
ao xml da visualização principal e depoispublic void stealFocusFromEditTexts(View view) {}
à sua atividade. O método on-click não precisa fazer nada, apenas deve existir para que a visualização pai seja focalizável / selecionável, o que é necessário para roubar o foco da criança. EditTextEu tenho mais uma solução para ocultar o teclado:
Aqui passe
HIDE_IMPLICIT_ONLY
na posição deshowFlag
e0
na posição dehiddenFlag
. Fechará com força o teclado virtual.fonte
Bem, eu consigo resolver um pouco o problema, substitui o dispatchTouchEvent na minha atividade, lá estou usando o seguinte para ocultar o teclado.
EDIT: O método getFields () é apenas um método que retorna uma matriz com os campos de texto na exibição. Para evitar criar essa matriz a cada toque, criei uma matriz estática chamada sFields, que é retornada no método getFields (). Essa matriz é inicializada nos métodos onStart (), como:
sFields = new EditText[] {mUserField, mPasswordField};
Não é perfeito. O horário do evento de arrastar é baseado apenas em heurísticas; portanto, às vezes, ele não se oculta ao executar cliques longos, e eu também terminei criando um método para obter todos os editTexts por exibição; caso contrário, o teclado ocultaria e mostraria ao clicar em outro EditText.
Ainda assim, soluções mais limpas e mais curtas são bem-vindas
fonte
getFields()
método? Não precisa ser exato, apenas um exemplo com talvez apenas alguns comentários indicando que ele retorna uma matriz deEditText
objetos.Use OnFocusChangeListener .
Por exemplo:
Atualização : você também pode substituir
onTouchEvent()
sua atividade e verificar as coordenadas do toque. Se as coordenadas estiverem fora do EditText, oculte o teclado.fonte
Eu implementei o dispatchTouchEvent na Activity para fazer isso:
e eu testei, funciona perfeito!
fonte
Uma maneira mais Kotlin e Design de materiais usando TextInputEditText (essa abordagem também é compatível com EditTextView ) ...
1.Faça clicável e focável a visualização pai (visualização de conteúdo de sua atividade / fragmento) adicionando os seguintes atributos
2.Crie uma extensão para todo o View (dentro de um arquivo ViewExtension.kt, por exemplo):
3.Crie um BaseTextInputEditText que herda de TextInputEditText. Implemente o método onFocusChanged para ocultar o teclado quando a exibição não estiver focada:
4. Basta chamar sua nova exibição personalizada em seu XML:
Isso é tudo. Não há necessidade de modificar seus controladores (fragmento ou atividade) para lidar com esse caso repetitivo.
fonte
Substituir público booleano dispatchTouchEvent (evento MotionEvent) em qualquer Atividade (ou estender a classe de Atividade)
E é tudo o que você precisa fazer
fonte
Modifiquei a solução de Andre Luis IM, consegui esta:
Criei um método utilitário para ocultar o teclado virtual da mesma maneira que Andre Luiz IM:
Mas, em vez de registrar um OnTouchListener para todas as visualizações, que apresentam um desempenho ruim, registrei o OnTouchListener apenas para a visualização raiz. Como o evento borbulha até ser consumido (o EditText é uma das visualizações que o consome por padrão), se chega à visualização raiz, é porque não foi consumido, por isso fecho o teclado virtual.
fonte
Estou ciente de que esse tópico é bastante antigo, a resposta correta parece válida e há muitas soluções de trabalho por aí, mas acho que a abordagem descrita abaixo pode ter um benefício adicional em relação à eficiência e elegância.
Como preciso desse comportamento para todas as minhas atividades, criei uma classe CustomActivity herdando da classe Activity e "liguei" a função dispatchTouchEvent . Existem principalmente duas condições para cuidar:
Este é o meu resultado:
Nota lateral: Além disso, atribuo esses atributos à visualização raiz, possibilitando limpar o foco em todos os campos de entrada e impedindo que os campos ganhem foco na inicialização da atividade (tornando o conteúdo visualizado como "coletor de foco"):
fonte
Gostei da abordagem de chamada
dispatchTouchEvent
feita pelo htafoya, mas:Então, eu fiz essa solução um pouco mais fácil:
Há uma desvantagem:
Mudar de um
EditText
para outroEditText
faz com que o teclado oculte e reapresente - no meu caso, é desejado dessa maneira, porque mostra que você alternou entre dois componentes de entrada.fonte
Fundamento: Reconheço que não tenho influência, mas leve a minha resposta a sério.
Problema: ignore o teclado virtual ao clicar fora do teclado ou edite o texto com o mínimo de código.
Solução: Biblioteca externa conhecida como Butterknife.
Solução de uma linha:
Solução mais legível:
Explicação: Vincule o OnClick Listener ao ID pai do Layout XML da atividade, para que qualquer clique no layout (não no texto ou teclado de edição) execute esse snippet de código que ocultará o teclado.
Exemplo: se o seu arquivo de layout for R.layout.my_layout e seu ID de layout for R.id.my_layout_id, sua chamada de ligação do Butterknife deverá se parecer com:
Link da documentação do Butterknife: http://jakewharton.github.io/butterknife/
Plug: Butterknife irá revolucionar o seu desenvolvimento Android. Considere isso.
Nota: O mesmo resultado pode ser alcançado sem o uso da biblioteca externa Butterknife. Basta definir um OnClickListener para o layout pai, conforme descrito acima.
fonte
No kotlin, podemos fazer o seguinte. Não há necessidade de iterar todas as visualizações. Também funcionará para fragmentos.
fonte
Aqui está outra variação da resposta do fje que aborda as questões levantadas pelo sosite.
A idéia aqui é lidar com as ações down e up no
dispatchTouchEvent
método da Activity . Na ação descendente, anotamos a visualização atualmente focada (se houver) e se o toque estava dentro dela, salvando essas informações para mais tarde.Na ação inicial, despachamos primeiro, para permitir que outra visualização potencialmente se concentre. Se depois disso, a visão atualmente focada for a visão originalmente focada e o toque para baixo estiver dentro dessa visão, deixaremos o teclado aberto.
Se a visualização atualmente focada for diferente da visualização originalmente focada e for uma
EditText
, também deixaremos o teclado aberto.Caso contrário, fechamos.
Então, para resumir, isso funciona da seguinte maneira:
EditText
, o teclado permanece abertoEditText
para outroEditText
, o teclado permanece aberto (não fecha / reabre)EditText
outroEditText
, o teclado fechaEditText
para exibir a barra de ação contextual (com os botões de recortar / copiar / colar), o teclado permanece aberto, mesmo que a ação UP tenha ocorrido fora do focoEditText
(que foi movido para baixo para dar espaço ao CAB) . Observe, porém, que quando você pressiona um botão no CAB, ele fecha o teclado. Isso pode ou não ser desejável; se você deseja cortar / copiar de um campo e colar em outro, seria. Se você deseja colar novamente no mesmoEditText
, não seria.quando o foco
EditText
está na parte inferior da tela e você clica prolongadamente em algum texto para selecioná-lo, eleEditText
mantém o foco e, portanto, o teclado abre como você deseja, porque fazemos a verificação "toque está dentro dos limites da vista" na ação para baixo , não a ação up.fonte
é muito simples, basta tornar seu layout recente clicável um foco por este código:
e, em seguida, escreva um método e um OnClickListner para esse layout, para que quando o layout mais alto for tocado em qualquer lugar em que ele chamará um método no qual você escreverá código para descartar o teclado. a seguir está o código para ambos; // você precisa escrever isso em OnCreate ()
método chamado do listner: -
fonte
Acho que o bit de resposta aceito é complexo para esse requisito simples. Aqui está o que funcionou para mim sem nenhuma falha.
fonte
NestedScrollView
layouts complexos, consulte a resposta aceita: stackoverflow.com/a/11656129/2914140 . Você deve saber que outros contêineres podem consumir toques.Existe uma abordagem mais simples, baseada no mesmo problema do iPhone. Basta substituir o layout do plano de fundo no evento de toque, onde o texto de edição está contido. Basta usar este código no OnCreate da atividade (login_fondo é o layout raiz):
fonte
Método para mostrar / ocultar o teclado virtual
Espero que tenham sido úteis
fonte
Esta é a solução mais fácil para mim (e elaborada por mim).
Este é o método para ocultar o teclado.
agora defina o atributo onclick do layout pai da atividade como o método acima
hideKeyboard
, na visualização Design do seu arquivo XML ou escrevendo o código abaixo na visualização Texto do seu arquivo XML.fonte
Refinei o método, coloque o código a seguir em alguma classe de utilitário da interface do usuário (de preferência, não necessariamente) para que ele possa ser acessado de todas as suas classes Activity ou Fragment para servir a seu propósito.
Então diga, por exemplo, que você precisa chamá-lo de atividade, chame-o da seguinte maneira;
Aviso prévio
Isso nos fornece a visualização raiz do grupo atual (você não deve ter definido o ID na visualização raiz).
Felicidades :)
fonte
Tente colocar stateHidden como seu
windowSoftInputMode
valor de atividadehttp://developer.android.com/reference/android/R.attr.html#windowSoftInputMode
Por exemplo, para sua atividade:
fonte
Atividade
ScreenUtils
fonte
Basta adicionar este código na classe @Overide
fonte
Em vez de iterar por todas as visualizações ou substituir o dispatchTouchEvent.
Por que não apenas substituir o onUserInteraction () da Atividade, isso garantirá que o teclado seja descartado sempre que o usuário tocar fora do EditText.
Funcionará mesmo quando o EditText estiver dentro do scrollView.
fonte
Consegui trabalhar com uma ligeira variante da solução de Fernando Camarago. No meu método onCreate, anexo um único onTouchListener à visualização raiz, mas a envio, em vez da atividade, como argumento.
Em uma classe Utils separada é ...
fonte
Isso pode ser antigo, mas eu consegui isso implementando uma classe personalizada
a melhor prática aqui é criar uma classe Helper e todos os layouts relativos / lineares de contêineres devem implementar isso.
**** Observe que apenas o contêiner principal deve implementar esta classe (para otimização) ****
e implementá-lo assim:
a palavra-chave é para Atividade. então, se você estiver no fragmento, use como getActivity ();
--- polegar para cima, se isso ajudá-lo ... --- aplaude Ralph ---
fonte
Esta é uma versão ligeiramente modificada da resposta de fje que funcionou perfeitamente na maioria das vezes.
Esta versão usa ACTION_DOWN, portanto, executar uma ação de rolagem também fecha o teclado. Também não propaga o evento, a menos que você clique em outro EditText. Isso significa que clicar em qualquer lugar fora do seu EditText, mesmo em outro clicável, simplesmente fecha o teclado.
fonte
view
eviewTmp
paragetCurrentFocus()
, para que eles sempre tenham o mesmo valor.Eu fiz assim:
Ocultar código do teclado :
Feito
fonte