expo: KeyboardAvoidingView does not work on standalone app [Android].

Hello.

I have taken this code from a premium theme that i bought.

<SafeAreaView style={styles.container}>
                <NavHeader title={thread.name} {...{navigation}} />
                <FlatList
                    inverted
                    data={messages}
                    keyExtractor={message => `${message.date}`}
                    renderItem={({ item }) => (
                        <Msg message={item} name={item.me ? name : thread.name} picture={thread.picture} />
                    )}
                />
                <KeyboardAvoidingView behavior={Platform.OS === "ios" ? "padding" : "height"}>
                    <View style={styles.footer}>
                        <TextInput
                            style={styles.input}
                            placeholder="Write a message"
                            value={this.state.message}
                            onChangeText={message => this.setState({ message })}
                            blurOnSubmit={false}
                            returnKeyType="send"
                            onSubmitEditing={this.send}
                            underlineColorAndroid="transparent"
                        />
                        <TouchableOpacity primary transparent onPress={this.send}>
                            <Text style={styles.btnText}>Send</Text>
                        </TouchableOpacity>
                    </View>
                </KeyboardAvoidingView>
            </SafeAreaView>

Its a chat View, it works perfect on Expo testing, but as soon as I build APK standalone it does not work, the keyboard will cover the whole screen.

I have tried react-native-keyboard-aware-scroll-view but in order to use its needed to detach the app.

I have searched the whole internet. I’m the only one suffering from this issue?

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 30
  • Comments: 79 (11 by maintainers)

Most upvoted comments

We seem to have found the issue causing the failure. Here is a repo reproducing the failure. The screen resizes properly and keeps the input on top of the keyboard in expo on the simulator. After building the standalone app for android and running the .apk on the same simulator, the screen doesn’t resize and the input is hidden by the keyboard.

Changing "splash": { "resizeMode": "cover" } to "splash": { "resizeMode": "contain" } in app.json fixes the issue we faced.

It doesn’t fix the issue for us – we already had contain for our resizeMode, and we’re seeing this issue.

We seem to have found the issue causing the failure. Here is a repo reproducing the failure. The screen resizes properly and keeps the input on top of the keyboard in expo on the simulator. After building the standalone app for android and running the .apk on the same simulator, the screen doesn’t resize and the input is hidden by the keyboard.

Changing "splash": { "resizeMode": "cover" } to "splash": { "resizeMode": "contain" } in app.json fixes the issue we faced.

Is this intentional behavior or a bug with expo build?

Hi! I had the same issue, on SDK 31 it was working with the “contain” workaround, but now (currently on SDK 33) it’s broken. The workaround that worked this time was to set splash on android on with “resizeMode”:“native” (also added the “padding” behavior on the KeyboardAwareScrollView ), hope this is solved soon, great work with expo!

I had the same issue, but I fixed it.

<KeyboardAvoidingView
        style={{flex: 1, justifyContent: 'center'}}
        keyboardVerticalOffset={30}
        behavior={Platform.OS === "ios" ? 'padding' : 'height'}
      >

It worked for the standalone app

@

Hi there!

I had been facing this problem for a few days and I finally managed to fix it. I had the following:

<KeyboardAvoidingView
  behavior={Platform.select({ android: null, ios: 'padding' })}
  style={{ flex: 1 }}
>
  <ScrollView
    contentContainerStyle={{ flex: 1 }}
    keyboardShouldPersistTaps='handled'
  >
    {children}
  </ScrollView>
</KeyboardAvoidingView>

It was working great on both simulators and devices (through Expo Client). When I built for iOS, it worked as expected. However, when I built for Android, the view didn’t scroll and the keyboard covered the input.

I tested different configurations (as provided in other comments) and the only one that worked for me was setting the behavior to height on Android:

<KeyboardAvoidingView
  behavior={Platform.select({ android: 'height', ios: 'padding' })}
  style={{ flex: 1 }}
>

Hope it solves your problem too!

thank you man you save me

I had the same issue. I just updated to Expo SDK v37 and it’s fixed. Have you tried updating to version 37?

Thanks @stanacton upgrade to SDK v37 and everything went back to normal

Hi all – I’m sorry that we haven’t been responsive to this issue. Apologies for the trouble this is continually causing.

We need a fully reproducible example in order to debug this issue. In the 72 comments on this thread, I have not found a single example I could use to successfully reproduce the issue – which to be clear is that KeyboardAvoidingView is behaving differently in the Expo client than in standalone apps – nor have I been able to find a repro case myself. 😞 Pasting code blocks into comments is not helpful in this case as we need the entire context of the app – including import statements, app.json settings, etc. – in order to reproduce the issue.

Could someone experiencing this issue please post a full MCVE that reproduces KeyboardAvoidingView behaving differently in the Expo client and standalone apps? Either a github repo or a snack (that can be easily copied + pasted and built into a standalone app) would be appropriate. Thank you!

https://github.com/expo/expo/issues/2172#issuecomment-420216938 This is my comment from September, in which a fully reproducible demo of the bug was provided.

Since then in SDK 33 the behavior of resizeMode: contain and resizeMode: cover was changed. My team and I were not able to get the behavior of SDK 32 back in our production app without completely removing the splash screen on Android.

hi there, we are having this issue since V31, do you know if its ever going to be fixed? Right now we have to set resizeMode on “native” in order to have keyboard avoiding scrolll… this is crazy! And many clients want big pictures on their splash, with native is imposible to make this happen in al resolutions without “empty” spaces…

Hey @michaelAdewunmi, unless you’re changing something in app.json each time, you could build an APK that points at a development channel and then publish to that channel to do an OTA update for each change you want to test. I was doing the same thing as you and this cut my dev cycle way down.

I had the same issue adding flex: 1 to KeyboardAvoidingView fixed my problem:

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

                <ScrollView >

                    <Card>

                        <CardItem header bordered>
                            <Text>Personal Information</Text>
                        </CardItem>

                        <CardItem bordered>

                            <Body>

                                <Item floatingLabel style={styles.item}>
                                    <Label>Full Name</Label>
                                    <Input />
                                </Item>

                                <Item floatingLabel style={styles.item}>
                                    <Label>Headline</Label>
                                    <Input />
                                </Item>

                                <Item floatingLabel style={styles.item}>
                                    <Label>Location</Label>
                                    <Input />
                                </Item>

                                <Item floatingLabel style={styles.item}>
                                    <Label>Email</Label>
                                    <Input />
                                </Item>

                                <Item floatingLabel style={styles.item}>
                                    <Label>Phone Number</Label>
                                    <Input />
                                </Item>
                                <Item floatingLabel style={styles.item}>
                                    <Label>Phone Number</Label>
                                    <Input />
                                </Item>
                                <Item floatingLabel style={styles.item}>
                                    <Label>Phone Number</Label>
                                    <Input />
                                </Item>

                            </Body>
                            
                        </CardItem>

                    </Card>

                    <ListItem>

                        <Left>
                            <Text>Make my Profile Public</Text>
                        </Left>

                        <Right>
                            <Switch value={this.state.publicProfileRadioValue}
                                onValueChange={(value) => this.setState({ publicProfileRadioValue: value })}
                            />
                        </Right>
                        
                    </ListItem>

                </ScrollView>

            </KeyboardAvoidingView>

+1

We are experiencing the same issue. Testing the app in expo on the simulator or on a device, Android and iOS resizes the view as expected, but on the standalone app built on expo the view doesn’t resize when opening the keyboard for Android.

We tested an apk built with expo on the 17th of July where the resize of views works in the standalone build. Rebuilding with the same codebase (from the 17th of July) and the current expo build process breaks the resizing of views.

We suspect that the problem originates from the windowSoftInputMode that might not be set correctly to adjustResize in the AndroidManifest.xml during the expo build or somehow has no effect.

Environment Expo sdk version: 28 / 29 Platform: Android

Hi there!

I had been facing this problem for a few days and I finally managed to fix it. I had the following:

<KeyboardAvoidingView
  behavior={Platform.select({ android: null, ios: 'padding' })}
  style={{ flex: 1 }}
>
  <ScrollView
    contentContainerStyle={{ flex: 1 }}
    keyboardShouldPersistTaps='handled'
  >
    {children}
  </ScrollView>
</KeyboardAvoidingView>

It was working great on both simulators and devices (through Expo Client). When I built for iOS, it worked as expected. However, when I built for Android, the view didn’t scroll and the keyboard covered the input.

I tested different configurations (as provided in other comments) and the only one that worked for me was setting the behavior to height on Android:

<KeyboardAvoidingView
  behavior={Platform.select({ android: 'height', ios: 'padding' })}
  style={{ flex: 1 }}
>

Hope it solves your problem too!

Just found out that if the StatusBar is hidden on android it breaks the KeyboardAware stuff. Even the keyboardDidShow event reports wrong height for the keyboard, so I can’t handle it manually. This is with "resizeMode" “contain” or “native”

This is really screwy. I’m on sdk33 and can’t figure out a way to solve this. Everything works perfectly in expo, breaks as standalone apk. Building for every debug attempt is horrible.

The splash fix was working for us in SDK 32 but now that we’ve upgraded to v33 I can’t find a combination that works anymore. Wasn’t the fix supposedly supplied by the version of React Native to be included in v33? https://github.com/expo/expo/issues/4154#issuecomment-490511370

Splash screens in expo are quite problematic. That problem with keyboard avoider is definitely because of splash screen (@expo - fix this please). Currently @MindFreeze solution works fine for both standalone and android emulator. This is my app.json for reference:

"expo": {
        "sdkVersion": "32.0.0",
        "splash": {
            "image": "./assets/images/splash_screen/contained/splash@2x.png",
            "resizeMode": "contain",
            "backgroundColor": "#0076F9"
        },
        "android": {
            "splash": {
                "backgroundColor": "#0076F9",
                "resizeMode": "cover",
                "mdpi": "./assets/images/splash_screen/splash.png",
                "hdpi": "./assets/images/splash_screen/splash@1.5x.png",
                "xhdpi": "./assets/images/splash_screen/splash@2x.png",
                "xxhdpi": "./assets/images/splash_screen/splash@3x.png",
                "xxxhdpi": "./assets/images/splash_screen/splash@4x.png"
            },
        },
        "ios": {
            "splash": {
                "backgroundColor": "#0076F9",
                "resizeMode": "cover",
                "image": "./assets/images/splash_screen/splash@2x.png"
            }
        },
}

2x image size is 1440x2560

I used expo.splash options because it seems that they actualy affect final result even if you override that options in android section. Maybe that is only my imagination but I’ve been building apks around 15 times already and actually bored of all this waste of time.

Also you will need to compensate status bar and header like this:

import {Header} from "react-navigation";
...
<KeyboardAvoidingView
     style={{flex: 1}}
     behavior={__DEV__ ? null : 'padding'}
     keyboardVerticalOffset={Platform.select({ios: 0, android: Header.HEIGHT + 20})}
>
    {this.props.children}
</KeyboardAvoidingView>

If you are not using header on some screens - remove Header.HEIGHT from keyboardVerticalOffset so that only status bar height (20) remains.

I’ve got the following combinations of parameters working:

splash.resizeMode: "cover" + <KeyboardAvoidingView bahavior="padding" Published app works, but DEV is messed up

splash.resizeMode: "contain" + <KeyboardAvoidingView bahavior={undefined} working in DEV

  • SDK v32

For those who arrived here, the thing to note is, you have to make sure that flex: 1 is applied to KeyboardAvoidingView and then also the element or View that you want to be affected by KeyboardAvoidingView. Otherwise, it won’t work. My mistake was that the TextInput I wanted to be keyboard avoided didn’t have flex: 1. Applying it made it work.

Love expo, but this bug is seriously annoying. In my scenario I have messaging app that looks like this: Fixed Header (height: 80) FlatList (Flex:1) Fixed Footer (height: 100), this where my KeyboardAvoidingView and TextInput are located.

For the life of me, I can’t get this to work in the standalone Android app, but it works fine when testing in Expo.

I’m basically trying every variation of settings for the KeyboardAvoidingView mentioned in this thread, doing an Android build, installing it on my phone and testing. Spending many hours on this…

UPDATED: Finally found a fix for my situation. I think the trick for me was to only have the FlatList as Flex:1.

Container (flex:1)
  Header(no flex)
  FlatList (flex:1)
  KeyboardAvoidingView (behavior = padding)
    View (height: 100)
      Form (flex:1)

I had the same issue. I just updated to Expo SDK v37 and it’s fixed. Have you tried updating to version 37?

Love expo, but this bug is seriously annoying. In my scenario I have messaging app that looks like this: Fixed Header (height: 80) FlatList (Flex:1) Fixed Footer (height: 100), this where my KeyboardAvoidingView and TextInput are located.

For the life of me, I can’t get this to work in the standalone Android app, but it works fine when testing in Expo.

I’m basically trying every variation of settings for the KeyboardAvoidingView mentioned in this thread, doing an Android build, installing it on my phone and testing. Spending many hours on this…

UPDATED: Finally found a fix for my situation. I think the trick for me was to only have the FlatList as Flex:1.

Container (flex:1)
  Header(no flex)
  FlatList (flex:1)
  KeyboardAvoidingView (behavior = padding)
    View (height: 100)
      Form (flex:1)

That craziness is exactly what shouldn’t be needed though.

@satya164, @esamelson - Is the cause of this know, and if so, has a specific fix been planned yet? Not trying to rush things, just hoping for an update.

Hello @BBARLOCCO @riguy14 . I Finally got it to work 😄 thanks to @BBARLOCCO solution with little addition of the “flex:1” to contentContainerStyle and style.

This was what worked for me <KeyboardAwareScrollView resetScrollToCoords={{ x: 0, y: 0 }} viewIsInsideTabBar={false} contentContainerStyle={[{minHeight: 532}, {overflow:"hidden", flex: 1}]} style={[Platform.OS === 'ios' ? {height:65}:{},{zIndex:50, flex: 1}]} scrollEnabled={true} enableAutomaticScroll={true}>RenderChildren()</KeyboardAwareScrollView >

I initially have my expo.splash.resizeMode set to “native” and this was the cause of the initial error. This was a mistake on my part as the required change was supposed to be done on expo.android.splash.resizeMode. I hope this helps anyone who might also be making this error. Oh and Thanks @riguy14 for the development channel builds and publishing. It has been a life saver.

Once again, Thanks guys! 👍

Hey @michaelAdewunmi, unless you’re changing something in app.json each time, you could build an APK that points at a development channel and then publish to that channel to do an OTA update for each change you want to test. I was doing the same thing as you and this cut my dev cycle way down.

Hello @riguy14. I just read about this now after seeing your comment. You are just about to save a life Bro 😀. I dont know if i understood what I read well but based on what you said and what I read on expo, this is what i need to do expo build:android --release-channel {my-channel}.

I will try this now and get back to you. Thanks a lot.

Using “native” for android fixed the problem but there is no splash in my case. So maybe just any word for resizeMode would work, haven’t tested. So, no splash or no KAView

@BBARLOCCO - Did you use KeyboardAwareScrollView around the iOS portion as well? Could you show an overview of the code in your component (iOS vs Android setup) please? 🙏I’m running into this issue when using GiftedChat and I can’t quite seem to find the right combination (OS specific splash screen setting, to use KAV or KASV, padding behavior, prod/dev etc). The fact that there’s so many variables for this is disheartening.

Have the same issue in SDK33. Any updates?

@Slapbox I created a new issue: #5073. I’m not sure if it aligns exactly with your problem but you can check it out.

@Slapbox I tried something like that, though used Constants.appOwnership. The problem is that KAV with ‘padding’ is not consistent for Android (for me). I am using a <View/> for android and it is working fine in expo (shrinks via padding automatically), but not when built. Where do you want me to open a bug report? Is this github issue not enough?

@seanpascoe

const behavior = process.env.NODE_ENV === 'production' ? 'padding' : undefined;
return <KeyboardAvoidingView behavior={behavior} />

This works for me to have proper behavior in DEV and PROD, but this can’t possibly be intentional. If this fixes your issue, please please please open a bug report, otherwise I will when I can, but it could be weeks before I have the time to file the complete issue template and supporting data.

+1 using SDK 31

+1 same experience on expo 32.0.0

I use behavior = __DEV__ ? null : 'padding' for Android, and for iOS I use react-native-keyboard-aware-scroll-view. Took a lot of trial and error to find this combination.

@pyankoff Your solution worked for me, I added: behavior={Constants.manifest.releaseChannel === 'production' ? 'padding' : null} to get it working in production (inside app) and dev (inside Expo). Although I didn’t have to change splash.resizeMode to contain for dev.

+1 here

The workaround proposed by @freshedgarT did solve the issue for me.

@hounsellal the drawback you commented can be easily bypassed by making your splash screen background transparent and defining a backgroundColor in the splash section. You can’t have a gradient background that way but it’s better than a white one =P

@RobertFischer be sure to generate a new apk. That is one of the changes that publish by itself is not enough. I’m saying that because I thought the workaround did not work after publishing, but after building an apk and installing it by hang everything worked great.

obs. I’m using expo sdk 30