Search code examples
react-nativekeyboard

How to use the react native Keyboard.scheduleLayoutAnimation(event) method?


I'm working on synchronizing a text input field with the iOS / Android system keyboards so that it sticks to the top of the keyboard, in the documentation for the react native Keyboard module it mentions this method:

scheduleLayoutAnimation

static scheduleLayoutAnimation(event)

Useful for syncing TextInput (or other keyboard accessory view) size of position changes with keyboard movements.

However I can't seem to find any further documentation or examples thus far, and my current implementation

Keyboard.scheduleLayoutAnimationscheduleLayoutAnimation((event: any ) => {
   console.log('[TextEditor] keyboard event:', event)
})

Throw the following error:

ExceptionsManager.js:179 TypeError: _reactNative.Keyboard.scheduleLayoutAnimationscheduleLayoutAnimation is not a function

Does any one have any experience with this method?

I'm currently on React Native 0.63.3 and testing on iOS 14.2, any help would be greatly appreciated, thanks!

Edit

I was able to get the function signature by calling:

Keyboard.scheduleLayoutAnimationscheduleLayoutAnimation.toString()

Which yields this definition:

function (event) {
    var duration = event.duration,
        easing = event.easing;

    if (duration != null && duration !== 0) {
      LayoutAnimation.configureNext({
        duration: duration,
        update: {
          duration: duration,
          type: easing != null && LayoutAnimation.Types[easing] || 'keyboard'
        }
      });
    }
  }

Maybe this is an issue with strict mode in TypeScript?


Solution

  • I don't know why there isn't any sample usage documented for this method as it looks it might be useful.

    Thanks to you I noticed that internally it used LayoutAnimation, here's the actual source for that method:

    node_modules/react-native/Libraries/Components/Keyboard/Keyboard.js

    KeyboardEventEmitter.scheduleLayoutAnimation = function(event: KeyboardEvent) {
      const {duration, easing} = event;
      if (duration != null && duration !== 0) {
        LayoutAnimation.configureNext({
          duration: duration,
          update: {
            duration: duration,
            type: (easing != null && LayoutAnimation.Types[easing]) || 'keyboard',
          },
        });
      }
    };
    
    module.exports = KeyboardEventEmitter;
    

    Regarding the exception - you have a typo

    Keyboard.scheduleLayoutAnimationscheduleLayoutAnimation
    

    vs

    Keyboard.scheduleLayoutAnimation
    

    scheduleLayoutAnimation does not work with a callback.

    This won't work

    Keyboard.scheduleLayoutAnimation((event: any ) => {
       console.log('[TextEditor] keyboard event:', event)
    })
    

    LayoutAnimation

    Keyboard.scheduleLayoutAnimation takes an object parameter named event. Looking at the implementation it's just a wrapper over LayoutAnimation.configureNext so you can use that instead for the same effects. LayoutAnimation.configureNext

    Only 2 parameters are used from the event - the name "event" is a bit confusing as it's used as a config for the animation

    const {duration, easing} = event;
    

    You can call the function like this:

    Keyboard.scheduleLayoutAnimation({ duration: 500 });
    // or
    Keyboard.scheduleLayoutAnimation({ duration: 500, easing: 'easeIn' });
    

    Right after this call you need to trigger something that will involve the keyboard. E.g. make it appear or disappear. See the examples in the linked documentation.

    easing is an optional parameter that falls back to "keyboard"

    • The available easings are from LayoutAnimation.Types - sprint, linear, easeIn/Out, keyboard.
    • This is another confusing thing - knowing the fact that there's a "keyboard" why would I pass something else? I guess "keyboard" stands for the default easing the keyboard animation uses, and providing other values you can make it more bouncy...

    I would assume the intended usage is something like this:

    Keyboard.scheduleLayoutAnimation({ duration: 500 });
    Keyboard.dismiss();
    

    or

    Keyboard.scheduleLayoutAnimation({ duration: 500 });
    myInputRef.focus();
    

    Since internally it just uses LayoutAnimation.configureNext the "scheduled" animation might get applied on something else that changes layout and not on the keyboard. If you don't interact with the keyboard it'll definitely be applied on something else. I wouldn't have expected that - I would expect that if I schedule a keyboard animation and I don't use the keyboard it won't be applied on something else as layout animation

    Anyway that's about it :)