12

I'm trying to make a sticky footer with the KeyboardAvoidingView component in React Native. I'm very close to accomplishing this task, however, when they keyboard comes up, the footer is moving up but shrinking in height at the same time.

Here's what it looks like before the keyboard comes up:

enter image description here

And here's what it looks like after the keyboard comes up:

enter image description here

As you can see, the submit container is smaller than it is before there is a keyboard.

Here's my current code:

render() {    
  return (
    <KeyboardAvoidingView style={{ flex: 1 }} behavior="padding">
      <View style={{ flex: 1, }}>
        <TextInput
          placeholder="Username"
          value={this.state.username}
          style={Styles.textInput}
          onChangeText={(username) => this.setState({ username })}
          autoCorrect={false}
        />
        <TextInput
          style={Styles.textInput}
          placeholder="Email"
          value={this.state.email}
          onChangeText={(email) => this.setState({ email })}
          autoCorrect={false}
        />
      </View>
      <View style={{ height: 100, backgroundColor: 'blue' }}>
        <Text>Submit</Text>
      </View>
    </KeyboardAvoidingView>
  );

What am I doing wrong?

Thomas
  • 2,356
  • 7
  • 23
  • 59
  • You never mentioned any intended behavior. What do you want to happen? With the way you wrote the code, it's doing exactly what it should be doing. – Michael Cheng Jul 08 '17 at 21:30
  • I want it to push the footer up, without resizing it to be smaller than it is when the keyboard is down @MichaelCheng – Thomas Jul 08 '17 at 21:56
  • If the height of the bottom view (the blue one) was only `30`, it would be hidden by the keyboard @MichaelCheng – Thomas Jul 08 '17 at 21:59

6 Answers6

13

Are you using react-navigation? This might be affected by the header of the react-navigation. The height of the header is vary on different mobile screen size. You need to get the get the height of the header and pass into the keyboardVerticalOffset props.

import { Header } from 'react-navigation';

 <KeyboardAvoidingView
  keyboardVerticalOffset = {Header.HEIGHT + 20}
  style = {{ flex: 1 }}
  behavior = "padding" >

  <ScrollView>
    <TextInput/>
    <TextInput/>
    <TextInput/>
    <TextInput/>
    <TextInput/>
    <TextInput/>
  </ScrollView> 

</KeyboardAvoidingView>
Benson Toh
  • 1,970
  • 1
  • 10
  • 13
3

My app uses react-navigation. So Toh Ban Soon's answer I ended up doing

import { KeyboardAvoidingView } from 'react-native';
import { Constants } from 'expo';
import { Header } from 'react-navigation';

<KeyboardAvoidingView behavior="padding" keyboardVerticalOffset = {Header.HEIGHT + Constants.statusBarHeight} style={[sharedStyles.container, {justifyContent: 'center'}]}>

... Input components...

</KeyboardAvoidingView>

There is an issue about it here https://github.com/react-navigation/react-navigation/issues/3971

chidimo
  • 2,684
  • 3
  • 32
  • 47
2

Stumbled across the same issue and wasn't able to solve it using the KeyboardAvoidingView. But here is a good alternative solution:

constructor() {
    super();
    this.state = {
        bottomHeight: 0
    }
}
componentDidMount() {
    this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', this._keyboardDidShow.bind(this));
    this.keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', this._keyboardDidHide.bind(this));
}
componentWillUnmount() {
    this.keyboardDidShowListener.remove();
    this.keyboardDidHideListener.remove();
}

_keyboardDidShow(e) {
    this.setState({ bottomHeight: e.endCoordinates.height - 50 })
}

_keyboardDidHide() {
    this.setState({ bottomHeight: 0 })
}

render() {
    return (
        <View style={{ flex: 1 }} behavior="padding">
            <View style={{ flex: 1, }}>
                <TextInput
                    placeholder="Username"
                    value={this.state.username}
                    style={Styles.textInput}
                    onChangeText={(username) => this.setState({ username })}
                    autoCorrect={false}
                />
                <TextInput
                    style={Styles.textInput}
                    placeholder="Email"
                    value={this.state.email}
                    onChangeText={(email) => this.setState({ email })}
                    autoCorrect={false}
                />
            </View>
            <View style={{ height: 100, backgroundColor: 'blue', position: 'absolute', left: 0, right: 0, bottom: this.state.bottomHeight }}>
                <Text>Submit</Text>
            </View>
        </View>

Hope this helps...

Pavlo Kyrylenko
  • 2,355
  • 2
  • 21
  • 21
0

For me helps to remove behavior="padding"

code looks just like this <KeyboardAvoidingView style={{flex: 1}}>

-1

Try following code, put footer at outer layer of scrollview and keyboardAvoidingView.

<ScrollView padder scrollEnabled={true}>
  <KeyboardAvoidingView
     behavior="padding"
     keyboardVerticalOffset={70}
  >
   <View style={{ flex: 1, }}>
     <TextInput
       placeholder="Username"
       value={this.state.username}
       style={Styles.textInput}
       onChangeText={(username) => this.setState({ username })}
       autoCorrect={false}
     />
     <TextInput
       style={Styles.textInput}
       placeholder="Email"
       value={this.state.email}
       onChangeText={(email) => this.setState({ email })}
       autoCorrect={false}
     />
   </View>
 </KeyboardAvoidingView>
</ScrollView>
<View style={{ height: 100, backgroundColor: 'blue' }}>
  <Text>Submit</Text>
</View>
elin
  • 538
  • 4
  • 6
-2

Try using native base npm package it is the best UI solution available for react native checkout this native base docs

Set up the header and footer as you like with the content tag behaving like scrollview

import React, { Component } from 'react';
import { Container, Header, Title, Content, Footer, FooterTab, Button, Left, Right, Body, Icon, Text } from 'native-base';
export default class AnatomyExample extends Component {
  render() {
    return (
      <Container>
        <Header />
        <Content>
          <TextInput
           placeholder="Username"
           value={this.state.username}
           style={Styles.textInput}
           onChangeText={(username) => this.setState({ username })}
           autoCorrect={false}
         />
         <TextInput
          style={Styles.textInput}
          placeholder="Email"
          value={this.state.email}
          onChangeText={(email) => this.setState({ email })}
          autoCorrect={false}
        />
        </Content>
        <Footer style={{backgroundColor: 'blue' }}>
          <FooterTab>
            <Button full onPress={()=>console.log('submitted')}>
              <Text>Submit</Text>
            </Button>
          </FooterTab>
        </Footer>
      </Container>
    );
  }
}
Aarsh Oza
  • 164
  • 1
  • 4
  • 19
  • I tried the solution but the footer isn't moving up. The link you provided did not mention anything about this issue. Please do not promote your product here if it's not related with the question. – RandyTek May 21 '20 at 00:29