skip to Main Content

I have a form wrapped inside a parent container (which is a KeyboardAvoidingView), and after adding the appropriate flex properties to center the form horizontally and vertically, the form does not center in either direction.

Here is the code for the parent container containing the form:

const AuthScreen = () => {
    const [isSignup, setIsSignup] = useState(false)

    return (
        <SafeAreaView style={{flex: 1}}>
            <PageContainer>
                <ScrollView>
                    <KeyboardAvoidingView style={styles.keyboardAvoidingView} behavior={Platform.OS === "ios" ? "height" : undefined} keyboardVerticalOffset={100}>
                        <LoginForm />
                    </KeyboardAvoidingView>
                </ScrollView>
            </PageContainer>
        </SafeAreaView>
    )
}

const styles = StyleSheet.create({
    keyboardAvoidingView: {
        padding: 10,
        alignItems: 'center',
        justifyContent: 'center',
        flex: 1,
    }
})

export default AuthScreen

Here is the form (LoginForm) code. This is the form I expect to be centered:

const LoginForm = () => {
  const [formState, dispatchFormState] = useReducer(reducer, initialState);

  const inputChangedHandler = useCallback((id, value) => {
    // Validate current input status
    const validationResult = validateInput(id, value)
    dispatchFormState({id, value, validationResult})
  }, [dispatchFormState])

  return (
    <>
       <Input errorText={formState.inputValidities["email"]} inputChanged={inputChangedHandler} id="email" placeholder="Email Address" /> 
       <Input errorText={formState.inputValidities["password"]}  inputChanged={inputChangedHandler} id="password" placeholder="Password" /> 
       <SubmitButton title='Login' />
    </>
  )
}

const styles = StyleSheet.create({
 
})

export default LoginForm

The code for the **Input **component:

const Input = props => {

    const {id, placeholder, inputChanged, errorText} = props

    return <View style={styles.container}>
        <View style={styles.inputContainer}>
            <TextInput onChangeText={(text) => inputChanged(id, text)} placeholderTextColor="white" style={styles.input} placeholder={placeholder} />
        </View>

        {
            errorText &&
            <View style={styles.errorContainer}>
                <Text style={{color: 'red'}}>{errorText[0]}</Text>
            </View>
        
        }
    </View>
}

const styles = StyleSheet.create({
    container: {
        width: '100%',
        marginTop: 32,
        alignItems: 'center',
    },
    input: {
        backgroundColor: colors.inputBgColor,
        flex: 1,
        paddingVertical: 6,
        paddingHorizontal: 12,
        letterSpacing: 0.3,
        color: 'white'
    },  
    inputContainer: {
        width: '100%',
        flexDirection: 'row',
        alignItems: 'center',
    },
    errorContainer: {
        alignItems: 'center',
        marginTop: 10
    }
})

export default Input

Could I get some ideas on why this form is not centering? Thank you.

2

Answers


  1. The issue with your code might be related to the combination of using a KeyboardAvoidingView and the flex property on the parent container. When using KeyboardAvoidingView and trying to center its content using flex, you might encounter unexpected behavior.

    Here’s a suggestion to fix the issue:

    1. Remove the flex: 1 from the keyboardAvoidingView style in AuthScreen. This will prevent the KeyboardAvoidingView from taking all the available space.

    2. Instead of using alignItems: 'center' and justifyContent: 'center' on the keyboardAvoidingView, apply these properties to the ScrollView and the PageContainer components. This will center the KeyboardAvoidingView within the ScrollView and the PageContainer within the SafeAreaView.

    Here’s the updated code for AuthScreen:

    const AuthScreen = () => {
        const [isSignup, setIsSignup] = useState(false);
    
        return (
            <SafeAreaView style={{ flex: 1 }}>
                <PageContainer style={styles.pageContainer}>
                    <ScrollView contentContainerStyle={styles.scrollViewContent}>
                        <KeyboardAvoidingView
                            style={styles.keyboardAvoidingView}
                            behavior={Platform.OS === "ios" ? "height" : undefined}
                            keyboardVerticalOffset={100}
                        >
                            <LoginForm />
                        </KeyboardAvoidingView>
                    </ScrollView>
                </PageContainer>
            </SafeAreaView>
        );
    };
    
    const styles = StyleSheet.create({
        pageContainer: {
            flex: 1,
            alignItems: 'center',
            justifyContent: 'center',
        },
        scrollViewContent: {
            flexGrow: 1,
            alignItems: 'center',
            justifyContent: 'center',
        },
        keyboardAvoidingView: {
            padding: 10,
        },
    });
    
    export default AuthScreen;
    

    Note that I added two new styles: pageContainer and scrollViewContent, which handle the centering of the content within the SafeAreaView and ScrollView, respectively.

    With this change, your LoginForm component should now be centered both horizontally and vertically.

    Login or Signup to reply.
  2. Use contentContainerStyle to apply style to the scroll view content container. Using flexGrow: 1 allows children to grow when needed.

    <ScrollView contentContainerStyle={{flexGrow: 1}}>
    ...
    </ScrollView>
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search