Usando WindowInsetsCompat
,
o app pode consultar e controlar o teclado na tela (também chamado de
IME), de forma semelhante
à maneira como ele interage com as barras do sistema. O app também pode usar
WindowInsetsAnimationCompat
para criar transições perfeitas quando o teclado de software é aberto ou fechado.
Pré-requisitos
Antes de configurar o controle e a animação do teclado de software, configure o app para exibir de borda a borda. Isso permite processar insets de janela do sistema, como as barras do sistema e o teclado na tela.
Verificar a visibilidade do teclado
Use WindowInsets
para verificar a visibilidade do
teclado do software.
Kotlin
val insets = ViewCompat.getRootWindowInsets(view) ?: return val imeVisible = insets.isVisible(WindowInsetsCompat.Type.ime()) val imeHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom
Java
WindowInsetsCompat insets = ViewCompat.getRootWindowInsets(view); boolean imeVisible = insets.isVisible(WindowInsetsCompat.Type.ime()); int imeHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom;
Como alternativa, use
ViewCompat.setOnApplyWindowInsetsListener
para observar mudanças na visibilidade do teclado de software.
Kotlin
ViewCompat.setOnApplyWindowInsetsListener(view) { _, insets -> val imeVisible = insets.isVisible(WindowInsetsCompat.Type.ime()) val imeHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom insets }
Java
ViewCompat.setOnApplyWindowInsetsListener(view, (v, insets) -> { boolean imeVisible = insets.isVisible(WindowInsetsCompat.Type.ime()); int imeHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom; return insets; });
Sincronizar a animação com o teclado de software
Quando um usuário toca em um campo de entrada de texto, o teclado desliza para o lugar na parte de baixo da tela, conforme mostrado no exemplo abaixo:
O exemplo "Desincronizado" na Figura 2 mostra o comportamento padrão no Android 10 (nível 29 da API), em que o campo de texto e o conteúdo do app são fixados no lugar em vez de serem sincronizados com a animação do teclado, um comportamento que pode ser visualmente perturbador.
No Android 11 (nível 30 da API) e versões mais recentes, é possível usar
WindowInsetsAnimationCompat
para sincronizar a transição do app com o teclado deslizando para cima e para baixo da parte de baixo da tela. Isso parece mais suave, como mostrado no exemplo "Sincronizado" na Figura 2.
Configure
WindowInsetsAnimationCompat.Callback
com a visualização a ser sincronizada com a animação do teclado.
Kotlin
ViewCompat.setWindowInsetsAnimationCallback( view, object : WindowInsetsAnimationCompat.Callback(DISPATCH_MODE_STOP) { // Override methods. } )
Java
ViewCompat.setWindowInsetsAnimationCallback( view, new WindowInsetsAnimationCompat.Callback( WindowInsetsAnimationCompat.Callback.DISPATCH_MODE_STOP ) { // Override methods. });
Há vários métodos para substituir em WindowInsetsAnimationCompat.Callback
,
como
onPrepare()
,
onStart()
,
onProgress()
e
onEnd()
.
Comece chamando onPrepare()
antes de qualquer mudança no layout.
O onPrepare
é chamado quando uma animação de encartes está começando e antes que as visualizações
sejam reposicionadas devido a uma animação. Você pode usá-lo para salvar o estado inicial,
que, neste caso, é a coordenada inferior da visualização.
O snippet a seguir mostra um exemplo de chamada para onPrepare
:
Kotlin
var startBottom = 0f override fun onPrepare( animation: WindowInsetsAnimationCompat ) { startBottom = view.bottom.toFloat() }
Java
float startBottom; @Override public void onPrepare( @NonNull WindowInsetsAnimationCompat animation ) { startBottom = view.getBottom(); }
onStart
é chamado quando uma animação de insetos começa. Você pode usá-lo para definir todas
as propriedades de visualização no estado final das mudanças de layout. Se você tiver um
callback OnApplyWindowInsetsListener
definido para qualquer uma das visualizações, ele já será
chamado neste ponto. Este é um bom momento para salvar o estado final das propriedades
de visualização.
O snippet abaixo mostra um exemplo de chamada para onStart
:
Kotlin
var endBottom = 0f override fun onStart( animation: WindowInsetsAnimationCompat, bounds: WindowInsetsAnimationCompat.BoundsCompat ): WindowInsetsAnimationCompat.BoundsCompat { // Record the position of the view after the IME transition. endBottom = view.bottom.toFloat() return bounds }
Java
float endBottom; @NonNull @Override public WindowInsetsAnimationCompat.BoundsCompat onStart( @NonNull WindowInsetsAnimationCompat animation, @NonNull WindowInsetsAnimationCompat.BoundsCompat bounds ) { endBottom = view.getBottom(); return bounds; }
O onProgress
é chamado quando os encartes mudam como parte da execução de uma animação.
Assim, você pode substituí-lo e receber uma notificação em cada frame durante a animação do
teclado. Atualize as propriedades da visualização para que ela seja animada em
sincronização com o teclado.
Todas as mudanças de layout estão concluídas nesse momento. Por exemplo, se você usar
View.translationY
para mudar a visualização, o valor vai diminuir gradualmente em cada
chamada desse método e, por fim, vai chegar a 0
na posição original do layout.
O snippet abaixo mostra um exemplo de chamada para onProgress
:
Kotlin
override fun onProgress( insets: WindowInsetsCompat, runningAnimations: MutableList<WindowInsetsAnimationCompat> ): WindowInsetsCompat { // Find an IME animation. val imeAnimation = runningAnimations.find { it.typeMask and WindowInsetsCompat.Type.ime() != 0 } ?: return insets // Offset the view based on the interpolated fraction of the IME animation. view.translationY = (startBottom - endBottom) * (1 - imeAnimation.interpolatedFraction) return insets }
Java
@NonNull @Override public WindowInsetsCompat onProgress( @NonNull WindowInsetsCompat insets, @NonNull List<WindowInsetsAnimationCompat> runningAnimations ) { // Find an IME animation. WindowInsetsAnimationCompat imeAnimation = null; for (WindowInsetsAnimationCompat animation : runningAnimations) { if ((animation.getTypeMask() & WindowInsetsCompat.Type.ime()) != 0) { imeAnimation = animation; break; } } if (imeAnimation != null) { // Offset the view based on the interpolated fraction of the IME animation. view.setTranslationY((startBottom - endBottom) * (1 - imeAnimation.getInterpolatedFraction())); } return insets; }
Se preferir, você pode substituir onEnd
. Esse método é chamado depois que a animação
termina. Esse é um bom momento para limpar as mudanças temporárias.
Outros recursos
- WindowInsetsAnimation no GitHub.