Utilizzando WindowInsetsCompat
,
la tua app può eseguire query e controllare la tastiera sullo schermo (chiamata anche
IME) in modo simile
a come interagisce con le barre di sistema. La tua app può anche utilizzare
WindowInsetsAnimationCompat
per creare transizioni fluide quando la tastiera software viene aperta o chiusa.
Prerequisiti
Prima di configurare il controllo e l'animazione per la tastiera software, configura la tua app in modo che venga visualizzata da bordo a bordo. In questo modo può gestire gli inset della finestra di sistema, ad esempio le barre di sistema e la tastiera sullo schermo.
Controllare la visibilità del software della tastiera
Utilizza WindowInsets
per controllare la visibilità della tastiera
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;
In alternativa, puoi utilizzare
ViewCompat.setOnApplyWindowInsetsListener
per osservare le modifiche alla visibilità della tastiera 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; });
Sincronizzare l'animazione con la tastiera software
Quando un utente tocca un campo di input di testo, la tastiera scorre in posizione dalla parte inferiore dello schermo, come mostrato nel seguente esempio:
L'esempio etichettato "Non sincronizzato" nella figura 2 mostra il comportamento predefinito in Android 10 (livello API 29), in cui il campo di testo e i contenuti dell'app si bloccano in posizione anziché sincronizzarsi con l'animazione della tastiera, un comportamento che può essere visivamente stridente.
In Android 11 (livello API 30) e versioni successive, puoi utilizzare
WindowInsetsAnimationCompat
per sincronizzare la transizione dell'app con lo scorrimento della tastiera verso l'alto e verso il basso dalla parte inferiore dello schermo. L'aspetto è più uniforme, come mostrato nell'esempio etichettato "Sincronizzato" nella Figura 2.
Configura
WindowInsetsAnimationCompat.Callback
con la visualizzazione da sincronizzare con l'animazione della tastiera.
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. });
Esistono diversi metodi per eseguire l'override in WindowInsetsAnimationCompat.Callback
,
ovvero
onPrepare()
,
onStart()
,
onProgress()
,
e
onEnd()
.
Inizia con la chiamata a onPrepare()
prima di apportare modifiche al layout.
onPrepare
viene chiamato quando un'animazione degli inset è in fase di avvio e prima che le visualizzazioni
vengano ridisposte a causa di un'animazione. Puoi utilizzarlo per salvare lo stato iniziale,
che in questo caso è la coordinata inferiore della visualizzazione.

onPrepare()
per
registrare lo stato iniziale.
Il seguente snippet mostra una chiamata di esempio a 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
viene chiamato all'avvio di un'animazione degli inset. Puoi utilizzarlo per impostare tutte le proprietà della visualizzazione sullo stato finale delle modifiche al layout. Se hai impostato un
callback OnApplyWindowInsetsListener
per una delle visualizzazioni, questo viene
già chiamato a questo punto. Questo è il momento giusto per salvare lo stato finale delle proprietà
della visualizzazione.

onStart()
per registrare
lo stato finale.
Il seguente snippet mostra una chiamata di esempio a 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; }
onProgress
viene chiamato quando i margini interni cambiano nell'ambito dell'esecuzione di un'animazione,
in modo da poterlo sostituire e ricevere una notifica su ogni frame durante l'animazione
della tastiera. Aggiorna le proprietà della visualizzazione in modo che l'animazione sia sincronizzata con la tastiera.
A questo punto, tutte le modifiche al layout sono state completate. Ad esempio, se utilizzi
View.translationY
per spostare la visualizzazione, il valore diminuisce gradualmente a ogni
chiamata di questo metodo e alla fine raggiunge 0
nella posizione del layout originale.
onProgress()
per
sincronizzare le animazioni.
Il seguente snippet mostra una chiamata di esempio a 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; }
In alternativa, puoi ignorare onEnd
. Questo metodo viene chiamato al termine dell'animazione. È il momento giusto per eliminare le modifiche temporanee.
Risorse aggiuntive
- WindowInsetsAnimation su GitHub.