Mit WindowInsetsCompat
kann Ihre App die Bildschirmtastatur (auch IME genannt) abfragen und steuern, ähnlich wie bei der Interaktion mit den Systemleisten. Deine App kann auch WindowInsetsAnimationCompat
verwenden, um nahtlose Übergänge beim Öffnen oder Schließen der Softwaretastatur zu schaffen.
Voraussetzungen
Bevor Sie die Steuerung und Animation für die Softwaretastatur einrichten, müssen Sie Ihre App so konfigurieren, dass sie randlos angezeigt wird. Auf diese Weise können Einfügungen des Systemfensters wie die Systemleisten und die Bildschirmtastatur verarbeitet werden.
Sichtbarkeit der Tastatursoftware prüfen
Mit WindowInsets
kannst du die Sichtbarkeit der Softwaretastatur prüfen.
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;
Alternativ können Sie ViewCompat.setOnApplyWindowInsetsListener
verwenden, um Änderungen an der Sichtbarkeit der Softwaretastatur zu beobachten.
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; });
Animation mit der Bildschirmtastatur synchronisieren
Wenn ein Nutzer auf ein Texteingabefeld tippt, schiebt sich die Tastatur vom unteren Bildschirmrand ein, wie im folgenden Beispiel gezeigt:
Das Beispiel mit der Bezeichnung „Nicht synchronisiert“ in Abbildung 2 zeigt das Standardverhalten in Android 10 (API-Ebene 29), bei dem das Textfeld und der Inhalt der App an der richtigen Stelle einrasten, anstatt mit der Animation der Tastatur zu synchronisieren. Dies kann visuell verwirrend sein.
Ab Android 11 (API-Level 30) kannst du
WindowInsetsAnimationCompat
verwenden, um den Übergang der App zu synchronisieren, wobei die Tastatur vom unteren Bildschirmrand nach oben und unten gleitet. Dies sieht gleichmäßiger aus, wie in dem Beispiel mit der Bezeichnung „Synchronisiert“ in Abbildung 2 gezeigt.
Konfigurieren Sie WindowInsetsAnimationCompat.Callback
mit der Ansicht, die mit der Tastaturanimation synchronisiert werden soll.
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. });
In WindowInsetsAnimationCompat.Callback
gibt es mehrere Methoden zum Überschreiben: onPrepare()
, onStart()
, onProgress()
und onEnd()
.
Rufe zuerst onPrepare()
auf, bevor du das Layout änderst.
onPrepare
wird aufgerufen, wenn eine Insets-Animation gestartet wird und bevor die Ansichten aufgrund einer Animation wieder eingeblendet werden. Sie können damit den Startstatus speichern, in diesem Fall die untere Koordinate der Ansicht.
![Ein Bild, auf dem die untere Koordinate des Startzustands der Stammansicht zu sehen ist.](https://developer.android.com/static/images/guide/navigation/software-keyboard-3.png?authuser=6&hl=de)
onPrepare()
, um den Startstatus aufzuzeichnen.
Das folgende Snippet zeigt einen Beispielaufruf für 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
wird aufgerufen, wenn eine Einfügungsanimation gestartet wird. Sie können damit alle Ansichtseigenschaften auf den Endstatus der Layoutänderungen setzen. Wenn ein OnApplyWindowInsetsListener
-Callback auf eine der Ansichten festgelegt ist, wird er an diesem Punkt bereits aufgerufen. An dieser Stelle empfiehlt es sich, den Endstatus der Ansichtseigenschaften zu speichern.
![Ein Bild, das die untere Koordinate des Endzustands der Ansicht zeigt](https://developer.android.com/static/images/guide/navigation/software-keyboard-4.png?authuser=6&hl=de)
onStart()
, um den Endzustand aufzuzeichnen.
Das folgende Snippet zeigt einen Beispielaufruf für 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
wird aufgerufen, wenn sich die Einfügungen im Rahmen der Ausführung einer Animation ändern. Sie können sie also überschreiben und während der Tastaturanimation bei jedem Frame eine Benachrichtigung erhalten. Aktualisieren Sie die Ansichtseigenschaften, damit die Ansicht synchron mit der Tastatur animiert wird.
Alle Layoutänderungen sind jetzt abgeschlossen. Wenn Sie beispielsweise View.translationY
verwenden, um die Ansicht zu verschieben, nimmt der Wert für jeden Aufruf dieser Methode allmählich ab und erreicht schließlich 0
an die ursprüngliche Layoutposition.
onProgress()
, um die Animationen zu synchronisieren.
Das folgende Snippet zeigt einen Beispielaufruf für 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; }
Optional können Sie onEnd
überschreiben. Diese Methode wird nach
der Animation aufgerufen. Dies ist ein guter Zeitpunkt, um alle temporären Änderungen zu entfernen.
Zusätzliche Ressourcen
- WindowInsetsAnimation auf GitHub.