Con WindowInsetsCompat
,
l'app può eseguire query e controllare la tastiera sullo schermo (anche chiamata
IME) simile all'
in che modo interagisce con le barre del sistema. La tua app può usare anche
WindowInsetsAnimationCompat
per creare transizioni fluide all'apertura o alla chiusura della tastiera software.
Prerequisiti
Prima di impostare il controllo e l'animazione per la tastiera software, configura dell'app in modo che sia display edge-to-edge. Ciò consente e gestire gli insiemi di finestre di sistema, come barre di sistema e la tastiera sullo schermo.
Controllare la visibilità del software della tastiera
Usa WindowInsets
per controllare il software
visibilità della tastiera.
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; });
Sincronizza l'animazione con la tastiera software
Un utente che tocca un campo di immissione di testo fa scorrere la tastiera in posizione nella parte inferiore dello schermo, come mostrato nell'esempio seguente:
L'esempio con l'etichetta "Non sincronizzato" nella figura 2 viene mostrato il comportamento predefinito in Android 10 (livello API 29), in cui il campo di testo e i contenuti dell'app scattare in posizione invece di sincronizzarsi con il tasto un'animazione: un comportamento visivamente fastidioso.
In Android 11 (livello API 30) e versioni successive, puoi utilizzare
WindowInsetsAnimationCompat
per sincronizzare la transizione dell'app con far scorrere la tastiera verso l'alto e verso il basso dalla parte inferiore dello schermo. Questo sembra in modo più fluido, come mostrato nell'esempio con la dicitura "Sincronizzato" come mostrato nella figura 2.
Configura
WindowInsetsAnimationCompat.Callback
con la vista 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
,
ossia
onPrepare()
,
onStart()
,
onProgress()
,
e
onEnd()
.
Inizia chiamando onPrepare()
prima di qualsiasi modifica del layout.
onPrepare
viene chiamato all'avvio di un'animazione contenente il riquadro e prima delle visualizzazioni
vengono riposizionati grazie a un'animazione. Puoi usarlo per salvare lo stato iniziale,
che in questo caso è la coordinata inferiore della vista.
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 contenente il riquadro. Puoi utilizzarlo per impostare
dalle proprietà della vista allo stato finale delle modifiche al layout. Se disponi di un
Il callback OnApplyWindowInsetsListener
impostato su una delle viste; è già
chiamato a questo punto. È un buon momento per salvare lo stato finale della vista
proprietà.
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 riquadri cambiano durante l'esecuzione di un'animazione,
in modo da poter eseguire l'override e ricevere una notifica su ogni frame mentre usi la tastiera
l'animazione. Aggiornare le proprietà della vista in modo che si anima la vista in
la sincronizzazione con la tastiera.
A questo punto tutte le modifiche al layout sono completate. Ad esempio, se utilizzi
View.translationY
per spostare la visualizzazione, il valore diminuisce gradualmente per ogni
di questo metodo e infine raggiunge 0
nella posizione originale del layout.
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; }
Se vuoi, puoi eseguire l'override di onEnd
. Questo metodo viene richiamato dopo l'animazione
è finita. È il momento giusto per eliminare eventuali modifiche temporanee.
Risorse aggiuntive
- Animazione WindowInsets su GitHub.