Con WindowInsetsCompat
, la tua app può eseguire query sulla tastiera sullo schermo (detta anche IME) e controllarla 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 impostare il controllo e l'animazione per la tastiera software, configura l'app per la visualizzazione perimetrale. In questo modo può gestire i set di finestre di sistema, ad esempio le barre di sistema e la tastiera sullo schermo.
Controlla la visibilità del software della tastiera
Utilizza WindowInsets
per controllare la visibilità della tastiera
del 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 immissione di testo, la tastiera scorre dalla parte inferiore dello schermo, come mostrato nell'esempio seguente:
L'esempio "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 entrano in posizione invece di sincronizzarsi con l'animazione della tastiera, un comportamento che può essere visivamente scioccante.
In Android 11 (livello API 30) e versioni successive, puoi utilizzare
WindowInsetsAnimationCompat
per sincronizzare la transizione dell'app facendo scorrere la tastiera verso l'alto e verso il basso dalla parte inferiore dello schermo. Questa operazione sembra più fluida, come mostrato nell'esempio con l'etichetta "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 qualsiasi modifica al layout.
onPrepare
viene chiamato quando inizia un'animazione dei riquadri e prima che le visualizzazioni
vengano riordinate a causa di un'animazione. Usala per salvare lo stato iniziale,
che in questo caso è la coordinata inferiore della vista.
Lo snippet seguente 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 insiemi. Puoi usarla per impostare tutte le proprietà
di vista sullo stato finale delle modifiche del layout. Se hai impostato un callback OnApplyWindowInsetsListener
su una delle visualizzazioni, questo viene già richiamato a questo punto. Questo è un buon momento per salvare lo stato finale delle proprietà
vista.
Lo snippet seguente 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 gli insiemi cambiano durante l'esecuzione di un'animazione,
quindi puoi sostituirli e ricevere una notifica su ogni frame durante l'animazione della
tastiera. Aggiorna le proprietà della vista in modo che l'animazione
della vista sia sincronizzata con la tastiera.
A questo punto, sono state completate tutte le modifiche al layout. 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
alla posizione del layout originale.
Lo snippet seguente 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; }
Se vuoi, puoi eseguire l'override di onEnd
. Questo metodo viene richiamato al termine
dell'animazione. Questo è un buon momento per eliminare eventuali modifiche temporanee.
Risorse aggiuntive
- WindowInsetsAnimation su GitHub.