When the keyboard meets Coroutines

Piotr Prus
Schibsted Tech Polska
3 min readJul 16, 2020

The keyboard management is one of the biggest problems of the Android platform since API 1. That was almost 12 years ago. However, there are mentions of a very promising API on the horizon. In Android 11, most probably, we will finally get the control of the Soft Input Keyboard. The SDK level 30 is right now in a beta stage (July 2020) and there is currently no evidence that these functions will work on older SDKs. You can wait for a support library, that will probably be in the alpha stage for some time, or you can check what are the other options to tame the beast.

View Tree Observer

The most popular way to check if the keyboard is visible to a user (since 2012), is checking the difference in height in your root view. This works nicely, but introduce some magic numbers.

Is 200dp hight difference is enough to know the keyboard is here, or maybe it should be 100dp or 300dp?

OnLayoutChangeListener

There is another way to check the difference in height of your view. The OnLayoutChangeListener. This interface is a part of View class, so it can be attached to any class that inherits from it. Let's see some code.

The onLayoutChange function has 9 different parameters, the view itself and 8 parameters describing the view ends, before and after the layout changes.

This function works very similarly to the ViewTreeObserver, however, it is simple to understand and simple to use. Also, what is important for a purpose of this article, is simple to wrap with coroutine. Check it out!

Suspend Cancellable Coroutine

Coroutines offer a way to write asynchronous non-blocking code in a sequential matter. It eliminates the need for listeners and callbacks, where a lot of nesting and decentralization might make your code unreadable and hard to understand.

The suspendableCancellableCoroutine gives us a great opportunity to give our listeners a second life.

Explanation of concept:

  • suspendCoroutine is a function that suspends the execution of the coroutine and Cancellable gives us the ability to react upon cancellation
  • remove the listener. After onLayoutChange will be called, we are removing the listener to do not observe the view anymore, and to do not leak the coroutine
  • cont.resume, we are waking up our coroutine from suspension and resume the continuation
  • cont.invokeOnCancellation, as mentioned above, using suspendCancellableCoroutine we have a chance to react upon cancellation. In this case, we will remove the listener to do not leak the coroutine.
  • addOnLayoutChangeListener, last but not least, we are registering our listener for a given view

The described function will be resumed after the view size change. We should focus on the reduction in Y direction only.

Usecase

Now, let’s think about the use case. When the keyboard opens, the available space in our app shrinks. In my opinion, that results in many use cases that UI needs to challenge. Knowing exactly when the keyboard appears, we can rearrange our view, start some animation, etc. Check the below pseudo-code for some inspiration

I am using this function to synchronize views animations together with a motion layout. With the help of coroutines, the animation looks smooth and I can easily control every step of the animation.

Lately, I was working with a keyboard opening and GIF container animation in the chat app. You can check the code below:

In my opinion, it is very legible. You can read it like a book and understand each step. There is one fragment to which additional attention should be paid, the one with a timeout:

withTimeoutOrNull(VIEW_HEIGHT_REDUCTION_TIMEOUT) {
binding.messagesRV.awaitsLayoutReductionInY()
}

The function withTimeoutOrNull, runs a given suspending block of code inside a coroutine with a specified timeout and returns null if this timeout was exceeded. I found it very useful when it comes to animations. Sometimes the Android system can hang a bit or freeze without any particular reason. In those cases, your function will finish execution.

One of the keyboard animation used in GoodOnes app

Gif about giphy :)

--

--

Piotr Prus
Schibsted Tech Polska

Android Developer @Tilt, Enthusiast of kotlin, jetpack compose and clean architecture. Currently Composing and KMMing all the things ❤️