Alex Ross
Alex Ross

Reputation: 85

KeyboardAvoidingView not working properly in iOS

I'm having trouble getting my KeyboardAvoidingView to register properly on the iOS version of my react-native app. It's nested within another view in my ListFooterComponent of a Flatlist. The behavior is relatively normal on Android, but is not working at all on iOS.

Things I've tried:

  1. Changing the behavior prop (all 3 props didn't end up working)
  2. Changing the keyboardVerticalOffset prop (no amount of offset managed to change anything, it just adds a bunch of padding to the bottom of the screen)
  3. Moving my KeyboardAvoidingView tag to the outermost view in ListFooterComponent. No difference
  4. Adding flex: 1 to inner and outer components

I have seen other posts recommending using other keyboard avoidance libraries, but since this is an Expo Managed project, I don't think these will work for me. Any advice for how to accomplish this using the KeyboardAvoidingView component only?

This is a screenshot of the screen without a keyboard on iOS: this

And this is a screenshot of with a keyboard on iOS: this

And here's the code:

        <SafeAreaView style={{ flex: 1 }}>

        <FlatList
            data={commentData}
            style={{ flex: 1 }}
            keyboardDismissMode={'on-drag'}
            keyboardShouldPersistTaps={'always'}
            keyExtractor={item => (item.id)}
            renderItem={({ item }) => {
                return (
                    <>

                    </>
                )
            }}
            ListFooterComponent={() => {
                return (
                    <>
                        <View style={{ borderColor: "#D6DCE8", marginBottom: 0, borderTopWidth: 2, marginTop: 25, shadowColor: "#000", shadowRadius: 2, shadowOpacity: 0.25, shadowOffset: { width: 0, height: 2 }, elevation: 5 }} />
                        <View style={{ flex: 1, flexDirection: 'row', paddingTop: 15, paddingBottom: 15 }}>
                            <TouchableOpacity delayPressIn={20}>
                                <View style={styles.commentImage}>
                                    <Image source={{ uri: myProfilePicture }} style={styles.image}></Image>
                                </View>
                            </TouchableOpacity>
                            <KeyboardAvoidingView
                                behavior={Platform.OS === "ios" ? "padding" : "height"}
                                keyboardVerticalOffset={Platform.select({ ios: 100, android: 500 })}
                                style={{ flex: 1, backgroundColor: '#ECECEC', borderRadius: 10, flex: 0.95, paddingVertical: 5, marginLeft: 10 }}>
                                <TextInput style={{
                                    fontSize: 14,
                                    fontWeight: '500',
                                    paddingHorizontal: 10,
                                    marginHorizontal: 10,
                                    paddingVertical: 6,
                                    flex: 1,
                                    flexDirection: 'row',
                                    flexWrap: 'wrap'
                                }}
                                    ref={commentRef}
                                    multiline={true}
                                    blurOnSubmit={true}
                                    numberOfLines={2}
                                    onFocus={() => commentRef.current = true}
                                    onBlur={() => commentRef.current = false}
                                    placeholder="Leave a comment..."
                                    defaultValue={comment}
                                    onChangeText={(newValue) => { comment = newValue }}
                                    onSubmitEditing={() => submitComment()} />
                            </KeyboardAvoidingView>
                        </View>
                        <View style={Platform.OS === 'android' ? { marginBottom: 200 } : { marginBottom: 100 }} />
                    </>
                )
            }}
            ListHeaderComponent={() => {
                return (
                    <>

                    </>
                )
            }}
        />

    </SafeAreaView>

Upvotes: 5

Views: 9200

Answers (1)

Marek Lisik
Marek Lisik

Reputation: 2185

For the above layout, use KeyboardAvoidingView above FlatList in your hierarchy, and place the comment box not as the footer, but outside of the list component altogether.

Here's a snack with these changes (OP's code simplified for context): https://snack.expo.dev/@mlisik/thankful-tortilla

A few general notes:

  • padding behaviour should be what you want
  • keyboarVerticalOffset is useful if your view is nested inside a navigator (eg. from react-navigation), and navigation bar or tabbar are visible - you should then set the value to the height of those bars
  • disable it on Android (unless you have disabled keyboard/soft input handling in your manifest).

Upvotes: 3

Related Questions