Animating your keyboard (part 2): reacting to WindowInset animations
Creating seamless keyboard animations using WindowInsetAnimation
In the previous blog post, we covered all of the changes to the APIs related to going edge-to-edge:
In this blog post we move forward on with the actual task of animating the keyboard. To demonstrate what is possible, here you can see an example of the same app, running on Android 10 on the left, and Android 11 on the right (at 20% speed):
On devices running Android 10 and before, when the user clicks on the text input to type a reply, the keyboard animates into place, but the app snaps between the states. This is the behaviour you’ve seen on your devices for a while, it’s just easier to see at 20% speed.
On the right you can see the same scenario running on Android 11. This time when the user clicks on the text input, the app moves with the keyboard, creating a more seamless experience.
So how can you add this experience to your app? Well it’s all powered by some new APIs…
The API which powers this in Android 11 is the new
WindowInsetsAnimation class, which encapsulates an animation involving insets. Apps can listen to animation events through the
WindowInsetsAnimation.Callback class, which can be set on a view:
So let’s just a look at the callback class, and the functions it provides:
Imagine that the keyboard is currently closed, and the user has just clicked on an
EditText. The system is now about to start showing the keyboard, and since we have a
WindowInsetsAnimation.Callback set, we’ll receive the following calls in order:
So that’s how the callback works in theory, now let’s apply it to a scenario…
Implementing the example
We’re going to use
WindowInsetsAnimation.Callback to implement the example which you saw at the beginning of this blog post. So lets start implementing our callback:
First we’ll override
onPrepare(), and record the bottom coordinate of the view, before any layout changes have happened:
At this point, the end-state insets will be dispatched, and our
OnApplyWindowInsetsListener called. Our listener updates the padding of the container view, which results in the content being pushed up.
The user never sees this though as we’ll see below.
Next we have our
onStart() function, which first allows us to record the end position of the view.
We also visually shift the view back down to its original position using
translationY, as we don’t want the user to see the end state right now. The user doesn’t see a flicker, as the system guarantees that any layout triggered from the inset pass above is called in the same frame as
Finally we override
onProgress() which allows us to update our view as the keyboard slides in.
translationY again, interpolating between the start and end states to move the view in unison with the keyboard.
And with that, we have achieved synchronization between the keyboard and the app’s views. If you would like to see a fully implementation, check out the WindowInsetsAnimation sample:
This sample shows how to react to the on-screen keyboard (IME) changing visibility, and also controlling the IME's…
Let us know on Twitter or the comments below if you add this to your app, and how you found it!
In the next blog post we will explore how your apps can control the keyboard, allowing things like list scrolling to automatically open the keyboard. Stay tuned!
If you try and implement this in your own views you may find that the techniques we talked about in this blog post can lead to view’s being clipped as they are animated. This is because we are translating views which may have been resized through the layout changes from your
We will explore in a future blog post how to combat this, but for now I recommend looking through the WindowInsetsAnimation sample, which contains one technique to avoid it.