Usando WindowInsetsCompat
,
seu app pode consultar e controlar o teclado na tela (também chamado de
IME) semelhante a
como ele interage com as barras do sistema. Seu 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 para o teclado de software, configure seu app para exibir de ponta a ponta. Isso permite ele lida com encartes de janela do sistema, como barras de sistema e o teclado na tela.
Verificar a visibilidade do software do teclado
Use WindowInsets
para verificar o software
visibilidade do teclado.
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 as 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 animação com o teclado de software
Um usuário tocando em um campo de entrada de texto faz com que o teclado deslize para o lugar da na parte de baixo da tela, como mostrado no exemplo a seguir:
O exemplo chamado "Unsynchronized" na Figura 2, mostramos o comportamento padrão no Android 10 (nível 29 da API), em que o campo de texto e o conteúdo do app se encaixe no lugar em vez de sincronizar com o animação, comportamento que pode ser visualmente desagradável.
No Android 11 (nível 30 da API) e versões mais recentes, é possível usar
WindowInsetsAnimationCompat
para sincronizar a transição do app. o teclado deslizando de baixo para cima na tela. Isto parece mais suave, como mostrado no exemplo intitulado "syncd" na Figura 2.
Configurar
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 de substituição em WindowInsetsAnimationCompat.Callback
,
ou seja,
onPrepare()
,
onStart()
,
onProgress()
,
e
onEnd()
.
Comece chamando onPrepare()
antes de qualquer mudança no layout.
onPrepare
é chamado quando uma animação de encartes está começando e antes das visualizações.
foram reposicionados devido a uma animação. É possível usá-lo para salvar o estado inicial,
que, neste caso, é a coordenada inferior da visualização.
![Uma imagem mostrando a coordenada inferior do estado inicial da visualização raiz.](https://developer.android.google.cn/static/images/guide/navigation/software-keyboard-3.png?authuser=19&hl=pt-br)
onPrepare()
para
registrar o estado inicial.
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 encarte é iniciada. Você pode usá-lo para definir todos
as propriedades de visualização para o estado final das mudanças do layout. Se você tiver um
O callback OnApplyWindowInsetsListener
foi definido para qualquer uma das visualizações, ele já está
chamado neste momento. Este é um bom momento para salvar o estado final da visualização.
propriedades.
![Uma imagem mostrando a coordenada inferior do estado final da visualização](https://developer.android.google.cn/static/images/guide/navigation/software-keyboard-4.png?authuser=19&hl=pt-br)
onStart()
para gravar
o estado final.
O snippet a seguir 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.
para que você possa substituí-lo e ser notificado em cada frame durante o teclado
animação. Atualizar as propriedades da visualização para que a visualização seja animada.
a sincronização com o teclado.
Todas as mudanças no layout estão concluídas nesse momento. Por exemplo, se você usar
View.translationY
para mudar a visualização, o valor diminui gradualmente a cada
chamada desse método e, eventualmente, chega a 0
para a posição original do layout.
onProgress()
para
sincronizar as animações.
O snippet a seguir 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; }
Opcionalmente, substitua onEnd
. Esse método é chamado após a animação
acabou. Esse é um bom momento para limpar quaisquer alterações temporárias.
Outros recursos
- WindowInsetsAnimation (link em inglês) no GitHub.