How to avoid keyboard pushing layout up on Android react-native
Asked Answered
T

14

66

I'm facing this issue for a few months and I still can't solve it. I have a text input at the bottom of the view that is supposed to rise up with the soft keyboard once tapped. Instead, the whole layout is pushed up and you can't see the upper part of it.

I tried many different keyboard spacer libraries but they all just push the TextInput even higher..

Screenshots: Without keyboard With keyboard

Here is my main View:

<View
    style={{
      flex: 1,
      alignItems: 'stretch',
      justifyContent: 'space-between',
      overflow: 'hidden',
      backgroundColor: Colors.darkBlue
    }}
  >
    {/* Header */}
    <View
      style={{
        flexDirection: 'row',
        alignItems: 'stretch',
        height: 300
      }}>
      {/* Question bubble */}
      { (this.state.question && this.state.question !== '') ? (
          <TouchableOpacity
            style={{
                flex: 1,
                flexDirection: 'row',
                backgroundColor: 'transparent',
                alignItems: 'stretch',
                paddingRight: QUESTION_SPEAKER_RADIUS
              }}
          >
            <View
              style={{
                  flex: 1,
                  alignSelf: 'stretch',
                  alignItems: 'center',
                  justifyContent: 'center',
                  backgroundColor: 'white',
                }}
            >
              <Text>
                {this.state.question}
              </Text>
            </View>
          </TouchableOpacity>
        ) : null
      }
    </View>
    <KeyboardInput
      style={{}}
      onClose={() => this.setState({ displayMode: DISPLAY_MODES.homeEmpty })}
      onConfirm={(text) => this.onConfirmText(text) }
    />
  </View>

Here is KeyboardInput:

<View
      style={{
        alignSelf: 'stretch',
        flexDirection: 'row',
        alignItems: 'center',
        justifyContent: 'flex-end',
        backgroundColor: Colors.pink,
        borderColor: Colors.lime,
        borderTopWidth: 4,
        padding: 6,
      }}>
      <View
        style={{
          flex: 1,
          borderRadius: 6,
          padding: 0,
          backgroundColor: Colors.white,
          alignItems: 'stretch',
        }}
      >
        <TextInput
          placeholder={Strings.child_keyboard_placeholder}
          value={this.state.messageTextInput}
          onChangeText={(text) => this.setState({messageTextInput: text})}
          style={{
            height: 50,
            marginLeft: 10,
            marginRight: CONFIRM_BUTTON_SIZE / 2
          }}
          underlineColorAndroid='transparent'
          numberOfLines={2}
          maxLength={70}
          autoCorrect={false}
          returnKeyType='next'
        />
      </View>
    </View>

Using RN 0.35 on Android.

Tender answered 16/3, 2017 at 17:8 Comment(3)
Using the RN KeyboardAvoidingView doesn't solve it. It just pushes the TextInput higher than the keyboardTender
I have android:windowSoftInputMode="adjustResize" in the manifest, and yet it doesn't work..Tender
If you are using expo, this can be easily solved with Expo SDK 38 and above. Check https://mcmap.net/q/297373/-view-moves-out-of-the-screen-when-text-input-is-focused-used-on-bottom-sheet-in-react-native-for-androidOscar
P
108

The problem here is that you have in your AndroidManifest.xml:

windowSoftInputMode="adjustResize";

Change it to:

windowSoftInputMode="adjustPan"

Note: after this change you'll need run ./gradlew clean in android folder and react-native run-android in your project directory

Pasteup answered 13/5, 2017 at 10:4 Comment(2)
adjustPan has the wrong effect, I want the window to resize when the keyboard shows, so that the view won't be pushed out of the screen.Tender
For those who had the same problem as me: After modifying the AndroidManifest.xml you have to re run the "react-native run-android" command.Daron
V
24

I tried all the solutions I could find in GitHub or stack overflow. Adding the following line of code in AndroidManifest.xml will be helpful.

I've tried this

windowSoftInputMode="adjustPan"

Sometimes it works but it misbehaves.

And then I came accross this

windowSoftInputMode="adjustResize"

This also misbehaves I finally combined both of them something like this and it works fine out of the box.

android:windowSoftInputMode="adjustPan|adjustResize"

And then you can use react-native KeyboardAvoidingView component.

<KeyboardAvoidingView
    style={{ flex: 1}}
    behavior={Platform.OS === 'ios' ? 'padding' : undefined}
    keyboardVerticalOffset={Platform.OS === 'ios' ? 40 : 0}
  >

Hope this helps you.

Vallery answered 10/8, 2019 at 13:44 Comment(1)
The setting must be one of the values listed in the following table, or a combination of one "state..." value plus one "adjust..." value. Setting multiple values in either group — multiple "state..." values, for example — has undefined resultsConservatory
O
14

putting

android:windowSoftInputMode="adjustNothing"

in Manifest worked for me.

Oast answered 23/6, 2018 at 23:35 Comment(2)
Just note that this will prevent keyboards from emitting events, documentationReber
It's not a solution for most of the asking people. Almost nobody wants to handle keyboard "manually" on each screen.Gobble
Z
13

All the answers are good, but didn't work when using expo.

Managed workflow

If using expo you can use softwareKeyboardLayoutMode like this inside app.json:

"android": {
  ...
  "softwareKeyboardLayoutMode": "pan"
},

You need to be on expo version 38.0.0+

Bare workflow

Otherwise, modifying AndroidManifest.xml works:

windowSoftInputMode="adjustPan"
Zulazulch answered 16/1, 2021 at 12:37 Comment(2)
This also worked for me. I needed to upgrade expo SDK to the latest version (49) with yarn add expo@^49.0.0. I had version 47 before and it didn't work until I upgraded itPercipient
if using editing "app.json" , dont forget to run the npx expo prebuild to update the manifestStacee
S
4

Setting

android:windowSoftInputMode="adjustPan"

on the MainActivity in AndroidManifest.xml worked for me !

However android:windowSoftInputMode="adjustNothing" is not suggested as it completely takes your freedom of making any design responsive to keyboard.

Serialize answered 4/6, 2019 at 18:9 Comment(0)
T
3

Well, thanks to the React Native FB group I got a solution: The status bar has to be not 'hidden' in order for this to work. Really weird bug..

Tender answered 16/3, 2017 at 19:8 Comment(1)
An issue was opened - github.com/facebook/react-native/issues/12980Tender
H
1

In your main 'AndroidManifest.xml' file change the android:windowSoftInputMode="adjustResize" to android:windowSoftInputMode="adjustPan" or android:windowSoftInputMode="adjustNothing".

'android:windowSoftInputMode="adjustNothing"' covers the part of the screen where the keyboard appears and hides the content that was there previously. Scrolling may not be possible while the keyboard is active.

android:windowSoftInputMode="adjustPan" pushes the selected input field above the keyboard and allows you to scroll without pushing the entire component out of place like android:windowSoftInputMode="adjustResize" does.

Heterogynous answered 25/11, 2020 at 12:59 Comment(0)
B
1

I am also facing that problem of "how to hide TAB.Navigation while keyboard is open ,now after searching i have found that ... so do tabBarHideOnKeyboard: true in your Tab.navigator , i am sure that it will help you e.g:

<Tab.Navigator
screenOptions={{
tabBarHideOnKeyboard: true
....//other options
 }}
/>
Billi answered 9/12, 2021 at 9:41 Comment(0)
S
0

Here are a couple deadly tutorials for anyone venturing into this area:

I will look very closely at the HOC solution myself shortly for this project, but for now, I just need this problem gone, which windowSoftInputMode="adjustPan" did for me.

With that, the keyboard just comes up over top of the view. With the default resize option, every component was using flex: 1 and justify/align center so the view got all kinds of mangled. Considering my view only has one input and is part of an 8 view, 8 step process, this is way too much work for me given the keyboard doesn't even go over top of the input with adjustPan.

But, in my opinion, the optimal solution is to use <KeyboardAvoidingView /> in conjunction with add and remove event listeners and swapping component styles with some state toggles. It's the only way to get full control over the UI on both Android and iOS through both keyboard states.

Saturniid answered 17/10, 2017 at 0:5 Comment(0)
H
0

The only solution that worked for me is:

Define keyboardVerticalOffset and put everything in a ScrollView put keyboardVerticalOffset={-500}

<KeyboardAvoidingView style = {styles.container} 
behavior="position" keyboardVerticalOffset={-550}>  

ScrollView
    TextInput

I tried many solutions from changing android windowsoft in XML to height of container and what not then I found this solution on Github.

Hardin answered 1/11, 2018 at 11:46 Comment(1)
why keyboardVerticalOffset 550, does it work with other devices?Adlare
F
0

I know this is late but this but the above answers didn't work for me. I tried KeyboardAvoidingView outside ScrollView with behavior={'padding'} as I guess behavior={'position'} has been messing with view. following is my code

<KeyboardAvoidingView behavior="padding">
   <ApplicationDetailsTabs
    initialIndex={this.state.activeTab}
    onChange={this.onTabChange}
    />
            <ScrollView style={styles.container}>
Fasano answered 9/12, 2020 at 4:27 Comment(0)
H
0

If you are using expo put inside app.json in android section:

"android": {
  ...
  "softwareKeyboardLayoutMode": "pan"
},

You need to be on expo version 38.0.0+

Helaine answered 12/6, 2022 at 7:45 Comment(0)
V
0

For someone who is still looking for a working solution: Try https://mateusz1913.github.io/react-native-avoid-softinput/ with android:windowSoftInputMode="adjustResize".

You may implement as following:

const YourReactNativeComponent = () => {
  ...

  const onFocusEffect = useCallback(() => {
    AvoidSoftInput.setAdjustNothing();
    return () => {
      AvoidSoftInput.setDefaultAppSoftInputMode();
    };
  }, []);

  useFocusEffect(onFocusEffect);

  ...
}

For me, this was the only solution that works for both bottom modal and scroll view.

Vera answered 22/5, 2024 at 6:34 Comment(0)
F
-2

I had a particular situation where the only way I could prevent this from happening was by giving the problematic TextInput a minHeight in its style.

Fronniah answered 7/2, 2020 at 22:37 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.