Mobile apps

Smooth keyboard animation on iOS mobile app with Capacitor

Frustrated by lag on keyboard transitions in your Capacitor iOS app? This guide will walk you through handling keyboard events and implementing a smooth transitions.

The problem

The reason of why there is a lag between keyboard animation on iOS and view is that Capacitor apps use input in web layer but the keyboard is in the native layer. It cause that keyboard transition / slide in are not in sync. Luckily there is a Capacitor Plugin which allows us to control behavior of keyboard. You can use it for setup keyboard event listeners and handle keyboard transition your way.

You can find Capacitor Keyboard plugin here.



This is the expected behavior:

Markup

This is a simple example of Vue markup which I use. 

<form @submit.prevent="join">
     <InputText id="game-id"  v-model="accessCode" />
     <Button type="submit" label="Join" :disabled="!valid"/>
</form>

I assuming that you have plugin already installed. 

If so - we need to configure capacitor.config.json and add "plugins" key there. It should look something like:

{
  "appId": "APP.ID.COM",
  "appName": "APPNAME",
  "webDir": "dist",
  "plugins": {
    "Keyboard": {
      "resize": "body"
    }
  },
  "server": {
    "androidScheme": "https"
  }
}

How to use keyboard plugin

if (Capacitor.getPlatform() == "ios") {
  let form = null;
  let kbHeight = 0;

  Keyboard.addListener('keyboardWillShow', info => {
    const input = document.activeElement;
    form = input.closest("form");

    if(!form){
      return;
    }

    const visibleArea = window.innerHeight - info.keyboardHeight;
    const formOffsetBottom = form.getBoundingClientRect().bottom + window.scrollY;
    form.style.transition = "all cubic-bezier(0.32, 0, 0.68, 1) 0.2s";

    if (kbHeight != 0) {
      return;
    }

    kbHeight = formOffsetBottom > visibleArea ? formOffsetBottom + 50 - visibleArea : 0;
    form.style.transform = "translateY(-" + kbHeight + "px)";
  });

  Keyboard.addListener('keyboardWillHide', () => {
    kbHeight = 0;
    form.style.transform = "translateY(-" + kbHeight + "px)";
  });
}

First, we check if the app is running on iOS. If so, we add event listeners.

"KeyboardWillShowEvent" fires every time just before the keyboard is toggled. This is a good time to get the active input element and form. Next, we calculate if the input will be visible when the keyboard is shown. If the input needs to move to be visible, then we add a CSS transform with a smooth transition to move it in a nice manner.


Note

My application only has simple forms, and I want the submit button to remain visible after the keyboard transition. If your app uses more complex forms, you might need to consider a different approach for calculating the height.

The second event, which is "keyboardWillHide" fires every time just before the keyboard is hided, so we just simply move form to initial value.

Summary

I've shown you my approach to handling keyboard transitions with Capacitor. I hope it's been helpful in your case. Let me know if you have any suggestions for this article.