Can't figure out how to properly use KeyboardAvoidingView

Viewed 4323

I'm developing an app using react native, we have screens layouts made by our designer. But I can't properly implement the expected behavior. Basically it's a screen with some text inputs and a button and I need for stuff to adjust correctly when the keyboard comes up. Here are the expected screens:

Without keyboard With keyboard

So when the keyboard comes up the button has to go up a lot, both the text inputs go up a bit, and that text on top stays put. The screen looks perfect without the keyboard, but right now it does nothing when the keyboard comes up. I've tried a lot of stuff, nothing really worked. Here is the render method now:

render() {
    const textInputBorderColor = this.state.hasError ? Colors.error : Colors.background;
    const textInputCpfMarginTop = this.state.hasError ? 24 : 48;

    return (
        <View style = {styles.container}>
            <KeyboardAvoidingView behavior='padding'>
                <Text style = {styles.headerText}>Vamos começar!</Text>
                
                <TextInput 
                    value = {this.props.user.name} 
            onChangeText = {text => this.props.user.name = text}
                    placeholder = 'Insira aqui seu nome completo'
                    style = {[styles.textInputName, {borderColor: textInputBorderColor}]}
                />

                <ErrorText show = {this.state.hasError} value = {this.state.errorMsg}/>

                <TextInputMask
                    value = {this.props.user.cpf}
                    onChangeText = {text => this.props.user.cpf = text}
                    placeholder = 'e aqui seu CPF'
                    keyboardType = 'numeric'
                    type = 'cpf'
                    style = {[styles.textInputCpf, {borderColor: Colors.background, marginTop: textInputCpfMarginTop}]}
                />
            
                <View style = {{marginTop: 202}}>
                    <DefaultButton 
                        onPress = {this.onButtonPress}
                        btnLabel = 'Continuar'
                        disabled = {(this.props.user.name == '' || this.props.user.cpf.length != 14)}
                    />
                </View>
            </KeyboardAvoidingView>
        </View>
    );
}

The styles:

const styles = StyleSheet.create({
    container: {
        flex: 1,
        backgroundColor: '#FFFFFF',
        alignItems: 'center',
    },

    textInputName: {
        textAlign: 'center',
        fontFamily: 'Roboto-Light',
        fontSize: 16,
        paddingBottom: ScreenDimensions.width * 0.01,
        borderBottomWidth: 1,
        marginTop: 96,
        width: 321
    },

    textInputCpf: {
        textAlign: 'center',
        fontFamily: 'Roboto-Light',
        fontSize: 16,
        paddingBottom: ScreenDimensions.width * 0.01,
        borderBottomWidth: 1,
        width: 321
    },
    
    headerText: {
        marginTop: 66,
        textAlign: 'center',
        fontFamily: 'Roboto-Light',
        fontSize: 20,
        color: '#000'
    }
})

The documentation on this component (keyboardAvoidingView) is worthless...

Thanks a lot for any help!

2 Answers

Forgot to post what worked for us. After some testing we were able to find a working solution. We surrounded the text inputs in a ScrollView so it works alright when using small screen devices, and only surronded the button with the KeyboardAvoidingView. Both are surrounded by an outer View.

Here is an example:

<View style = {{flex: 1, alignItems: 'center', justifyContent: 'flex-end'}}>
  <ScrollView 
    contentContainerStyle={{ flexGrow: 1, justifyContent: 'center' }}
    style={{ alignSelf: 'stretch' }}
  >
    # Your Text Inputs
  </ScrollView>

  <KeyboardAvoidingView
    behavior='padding'
    keyboardVerticalOffset={Platform.OS == 'ios' ? Header.HEIGHT + getStatusBarHeight() : Header.HEIGHT + 32}
    style={{ flex: 1, justifyContent: 'flex-end', alignSelf: 'stretch', marginBottom: 16 }}
  >
    # Yout Button
  </KeyboardAvoidingView>
</View>

SIDE NOTE: BEWARE when using text inputs and buttons inside ScrollViews (which is not the case of my solution), as there is a small problem where you can't click the button with the keyboard open.

Try this:

const keyboardAvoidingViewBehaviour = (Platform.OS === 'ios') ? 'padding' : null;

use KeyboardAvoiding view as root component, no need for extra view.

        <KeyboardAvoidingView 
           behavior={keyboardAvoidingViewBehaviour}
           style = {styles.container} // <-- have flex: 1 as one of the style props here
        >
            <Text style = {styles.headerText}>Vamos começar!</Text>

            <TextInput
            // ...

If your content needs scrolling a good option would be:

react-native-keyboard-aware-scroll-view

https://github.com/APSL/react-native-keyboard-aware-scroll-view

Related