Keyboard covers input android standalone app

Hello,

I’m using expo version 30 and i can’t manage to have a working form.
The different solutions found seems to work on expo but not on the standalone app.

Every time i focus a text input, the keyboard covers everything and the scrolling does not work.
I tried to wrap the whole UI with KeyboardAvoidingView with all variations (padding, position etc.) or KeyboardAwareScrollView or ScrollView etc.
Nothing works correctly (input half visible, abnormal scrolling, strange behavior in ios etc.).

My app.json is containing the androidStatusBar hack as well.

Is there a working solution for this basic problem ?

Thank you for your help !

Are you just having issues in Android, or iOS, as well?

I’ve had success with the standard <KeyboardAvoidingView>, like this:

<KeyboardAvoidingView style={{ flex: 1 }} behavior="padding">
<ScrollView />
</KeyboardAvoidingView>

Though I actually prefer GitHub - Andr3wHur5t/react-native-keyboard-spacer: Plug and play react-native keyboard spacer view., e.g.,

<View style={{flex: 1}}>
   <ScrollView />
   <KeyboardSpacer />
</View>

I assume the Android status bar hack is the thing where you make the status bar no longer transparent, which ends up changing some stuff under the hood in AndroidManifest.xml? I’d stay away from that, just because transparent status bars are more of what’s done on modern Android apps, and they actually prevent keyboard spacer components from working correctly.

***UPDATE: There’s a good chance you don’t need any of the information below. If your user scrolls to a TextInput and taps it, there’s a good chance that just using a keyboard spacer or setting contentInset will be enough. We had a use case where we animated expanding view and then focused a TextInput in a particular position as cell in the list was tapped, and that’s when we had to resort to the more advanced stuff below. Just try the basics first and see how it serves you.


Now, what I just was talking about is fine for keeping the keyboard from covering the UI. It will not necessarily scroll your scroll view to the correct position so the TextInput is on the screen. Making a TextInput always visible is actually kind of a pain. Some of my most hacky code is to make this work all the time on both platforms.

iOS mostly does this automatically when you focus an input. I find iOS works better if you don’t use the keyboard spacer and instead set contentInset on the scrollview to { bottom: heightOfKeyboard }, where you get the value for heightOfKeyboard from the callback from Keyboard.addListener(). KeyboardAwareScrollView does this.

For Android, you can scroll to the currently focused TextInput. Apologies if this looks like spaghetti, because it kind of is:

_androidTrackToFocusedTextInput = () => {
    const currentlyFocusedField = TextInput.State.currentlyFocusedField();
    const scrollResponder = this._scrollViewRef && this._scrollViewRef.getScrollResponder();
    // obviously there could be no currently focused field
    // Forget why there sometimes isn't a scroll responder.
    // Could be due to popping a child view in navigation.
    if (currentlyFocusedField && scrollResponder) {
      UIManager.viewIsDescendantOf(
        currentlyFocusedField,
        scrollResponder.getInnerViewNode(),
        isDescendant => {
          // Do not try to scroll if this text field isn't even within this scrollview
          // (e.g., maybe we pushed another screen that also scrolls and has text fields)
          if (!isDescendant) {
            return;
          }
          // Async so scroll responder could have gone away in meantime
          const scrollResponder = this._scrollViewRef.getScrollResponder();
          setTimeout(() => {
            const nodeHandle = findNodeHandle(currentlyFocusedField);
            scrollResponder.scrollResponderScrollNativeHandleToKeyboard(
              nodeHandle,
              100 /* extra space between the TextInput and keyboard, your choice here */,
              // This should prevent scrolling down to meet text input
              // We only want to scroll up
              true
            );
          }, 200 /* some kind of delay here */);
        }
      );
    }
  };

I call that whenever the keyboard shows (Keyboard.addListener( 'keyboardDidShow',).

Note that it doesn’t help if you need to automatically scroll to another TextInput that’s offscreen that was focused directly after your first TextInput was focused.

1 Like

Hello,
Thank you very much for such an explanation !

The results with KeyboardSpacer seems promising. I’ll try to create a custom solution with this and the keyboard listeners.
The problem was specifically on android though.

Thank you for you help,
regards