Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In React Native, How Can I Use KeyboardAvoidingView with a Modal in iOS?

I am having trouble getting a KeyboardAvoidingView to work in iOS, specifically when wrapping a Modal in it. Testing in Android, the Modal avoids the keyboard correctly, but in iOS the keyboard covers the Modal.

Here is a reproducible example, using an iPhone X as my test device:

import React, {useState} from 'react';
import {StyleSheet, ScrollView, View, Modal, TextInput, KeyboardAvoidingView, Button, SafeAreaView} from 'react-native';

export default function App() {
    const [modalVisible, setModalVisible] = useState(false);

    return (
        <View style={styles.container}>
            <Button title={"Open Modal"} onPress={() => setModalVisible(true)}/>
            {modalVisible && 
            <KeyboardAvoidingView behavior={Platform.OS === "ios" ? "padding" : "height"}>
                <Modal
                    animationType="slide"
                    transparent={true}
                    visible={modalVisible}>
                    <SafeAreaView style={styles.safeAreaView}>
                        <View style={styles.modalContentContainer}>
                            <Button title={"Close Modal"} onPress={() => setModalVisible(false)}/>
                            <ScrollView>
                                <View style={styles.textInputContainer}>
                                    <TextInput
                                        value={"test 1"}
                                        onChangeText={() => {}}
                                        onBlur={() => {}}
                                    />
                                </View>
                                <View style={styles.textInputContainer}>
                                    <TextInput
                                        value={"test 2"}
                                        onChangeText={() => {}}
                                        onBlur={() => {}}
                                    />
                                </View>
                                <View style={styles.textInputContainer}>
                                    <TextInput
                                        value={"test 3"}
                                        onChangeText={() => {}}
                                        onBlur={() => {}}
                                    />
                                </View>
                                <View style={styles.textInputContainer}>
                                    <TextInput
                                        value={"test 4"}
                                        onChangeText={() => {}}
                                        onBlur={() => {}}
                                    />
                                </View>
                            </ScrollView>
                        </View>
                    </SafeAreaView>
                </Modal>
            </KeyboardAvoidingView>}
        </View>
    );
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        backgroundColor: '#fff',
        alignItems: 'center',
        paddingTop: 50
    },
    safeAreaView: {
        flex: 1,
        justifyContent: "center",
        alignItems: "center",
    },
    modalContentContainer: {
        margin: 100,
        backgroundColor: "#d6d6d6",
        width: "80%",
        height: "60%",
        borderRadius: 10,
    },
    textInputContainer: {
        flex: 1,
        margin: 40,
        alignItems: "center",
    }
});

You will notice that when you open the Modal and tap on the last TextInput field, the keyboard comes up and covers the Modal. The Modal does not avoid the keyboard, as would be expected.

Here is a screenshot from my testing in iOS, where it is not working:

iOS not working

And here is a screenshot from my testing in Android, where it is working:

Android working

Any ideas on how I can make a Modal avoid the keyboard in iOS?

like image 727
MoreFoam Avatar asked Nov 25 '25 16:11

MoreFoam


2 Answers

If you're using react-native-modal package ... avoidKeyboard attribute would do the trick...

import Modal from "react-native-modal";

return (
    <Modal
        avoidKeyboard
        /** rest props */
    >
        {/* Content goes here */}
    </Modal>
);

Not in the build-in-react-native-modal ... it's in react-native-modal here

like image 120
Hend El-Sahli Avatar answered Nov 27 '25 04:11

Hend El-Sahli


You are wrapping your Modal with a KeyboardAvoidingView. I'm not sure about this but from my testing it seems to be impossible to resize a Modal using a KeyboardAvoidingView.

So move the KeyboardAvoidingView inside of the Modal to get the expected behaviour. Like this:

return (
        <View style={styles.container}>
            <Button title={"Open Modal"} onPress={() => setModalVisible(true)}/>
            {modalVisible && 
                <Modal
                    animationType="slide"
                    transparent={true}
                    visible={modalVisible}>
                      <KeyboardAvoidingView behavior={"padding"} style={styles.safeAreaView}>
                        <View style={styles.modalContentContainer}>
                            <Button title={"Close Modal"} onPress={() => setModalVisible(false)}/>
                            <ScrollView>
                                <View style={styles.textInputContainer}>
                                    <TextInput
                                        value={"test 1"}
                                        onChangeText={() => {}}
                                        onBlur={() => {}}
                                    />
                                </View>
                                <View style={styles.textInputContainer}>
                                    <TextInput
                                        value={"test 2"}
                                        onChangeText={() => {}}
                                        onBlur={() => {}}
                                    />
                                </View>
                                <View style={styles.textInputContainer}>
                                    <TextInput
                                        value={"test 3"}
                                        onChangeText={() => {}}
                                        onBlur={() => {}}
                                    />
                                </View>
                                <View style={styles.textInputContainer}>
                                    <TextInput
                                        value={"test 4"}
                                        onChangeText={() => {}}
                                        onBlur={() => {}}
                                    />
                                </View>
                            </ScrollView>
                        </View>
                    </KeyboardAvoidingView>
                </Modal>}
        </View>
    );

I've also removed your SafeAreaView since it currently doesn't do anything. Your parent is already centered and its content will never reach the 'unsafe' areas of a device.

You might as well remove the {modalVisible && ...} from your code since visible={modalVisible} already hides and shows the modal when needed.

Demo: https://i.sstatic.net/TMcGh.jpg

like image 21
Kipnoedels Avatar answered Nov 27 '25 05:11

Kipnoedels



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!