32

I am using react-native TextInput component. Here I need to show the InputBox above the keyboard if the user clicks on the textInput field.

I have tried below but i am facing the issues

1. Keyboard avoiding view

 a. Here it shows some empty space below the input box 
 b. Manually I need to scroll up the screen to see the input field which I was given in the text field
 c. Input box section is hiding while placing the mouse inside the input box 

2. react-native-Keyboard-aware-scroll-view

a.It shows some empty space below the input box
b.ScrollView is reset to the top of the page after I moving to the next input box

Here I set the Keyboard-aware-scroll-view inside the ScrollView component

Kindly clarify

My example code is

<SafeAreaView>
<KeyboardAvoidingView>
<ScrollView>        
        <Text>Name</Text>
            <AutoTags
            //required
             suggestions={this.state.suggestedName}
             handleAddition={this.handleAddition}
             handleDelete={this.handleDelete}
             multiline={true}
             placeholder="TYPE IN"
             blurOnSubmit={true}
             style= {styles.style}
             />
</ScrollView>   
</KeyboardAvoidingView>
</SafeAreaView>

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

sejn
  • 2,040
  • 6
  • 28
  • 82
  • try setting behviour for KeyboardAvoidingView, and make sure your contianer view style is flex – Omar Samman Feb 06 '19 at 08:24
  • I have set behaviour = 'padding' style = {{flex:1 }}for KeyboardAvoidingView. NAME placeholder="TYPE IN"/> – sejn Feb 06 '19 at 11:46
  • I need this like behaviour in react native. When moving to text input box the keyboard opened and dismissed after return.https://github.com/Just-/UIViewController-KeyboardAnimation – sejn Feb 06 '19 at 12:03
  • can you try taking out the `` tags and place just one outside the ``? – kenmistry Feb 28 '19 at 13:51
  • not sure why you rolled back my edits. it would certainly help if you can place the code in your description of the issue. – kenmistry Mar 02 '19 at 13:31
  • @kenmistry I have added my example code. It will not shows the inputText box above the keyboard. I want to scrollup to see which input I am giving in the text box. Autotags has the same properties of the TextInput box. – sejn Mar 04 '19 at 03:42

17 Answers17

15

You can use a scrollview and put all components inside the scrollview and add automaticallyAdjustKeyboardInsets property to scrollview.it will solve your problem.

automaticallyAdjustKeyboardInsets Controls whether the ScrollView should automatically adjust its contentInset and scrollViewInsets when the Keyboard changes its size. The default value is false.

<ScrollView automaticallyAdjustKeyboardInsets={true}>

          {allChildComponentsHere}
         <View style={{ height: 30 }} />//added some extra space to last element
</ScrollView>

Hope it helps.

Sandeep Parish
  • 1,888
  • 2
  • 9
  • 20
14

Give your TextInput a position: absolute styling and change its position using the height returned by the keyboardDidShow and keyboardDidHide events.

Here is a modification of the Keyboard example from the React Native documentation for demonstration:

import React, { Component } from 'react';
import { Keyboard, TextInput } from 'react-native';

class Example extends Component {
    state = {
        keyboardOffset: 0,
    };

    componentDidMount() {
        this.keyboardDidShowListener = Keyboard.addListener(
            'keyboardDidShow',
            this._keyboardDidShow,
        );
        this.keyboardDidHideListener = Keyboard.addListener(
            'keyboardDidHide',
            this._keyboardDidHide,
        );
    }

    componentWillUnmount() {
        this.keyboardDidShowListener.remove();
        this.keyboardDidHideListener.remove();
    }

    _keyboardDidShow(event) {
        this.setState({
            keyboardOffset: event.endCoordinates.height,
        })
    }

    _keyboardDidHide() {
        this.setState({
            keyboardOffset: 0,
        })
    }

    render() {
        return <View style={{flex: 1}}>
            <TextInput
                style={{
                    position: 'absolute',
                    width:    '100%',
                    bottom:   this.state.keyboardOffset,
                }}
                onSubmitEditing={Keyboard.dismiss}
            />
        </View>;
    }
}
basbase
  • 1,225
  • 7
  • 19
  • 1
    I have tried with this. But it not worked as I expected in AutoTags – sejn Jun 17 '19 at 10:14
  • Hi, I am trying the code above, but I have noticed that the page content, which in my case is a `FlatList` jumps cuz of the `bottom: this.state.keyboardOffset`. Also, it seems that `event.endCoordinates.height` returns a higher value than the keyboard, cuz there is a gap between the `TextInput` and `Keyboard`. – Yasir Oct 02 '19 at 10:18
  • @Yasir "absolute" positioned elements are relative to their containing view, which may differ in size from the device. If your TextInput is inside a container that is smaller than the device height, you need to account for difference in height between container and device. Here's a formula that worked for me to position a "Text" view directly above the keyboard: `bottom: keyboardHeight - ((deviceHeight - containerHeight) / 2)`. I have a top and bottom bar, with my Text view in a container between, so I accounted for the diff between device height and my container. – StoriKnow May 02 '20 at 16:30
  • 1
    dont do this, this cause layout laggy – famfamfam Jul 25 '22 at 07:55
12

First of all, You don't need any extra code for Android platform. Only keep your inputs inside a ScrollView. Just use KeyboardAvoidingView to encapsulate the ScrollView for iOS platform.

Create function such as below which holds all the inputs

renderInputs = () => {
    return (<ScrollView
        showsVerticalScrollIndicator={false}
        style={{
            flex: 1,
        }}
        contentContainerStyle={{
            flexGrow: 1,
        }}>
        <Text>Enter Email</Text>
        <TextInput
            style={styles.text}
            underlineColorAndroid="transparent"
        />
    </ScrollView>)
}

Then render them inside the main view as below

{Platform.OS === 'android' ? (
    this.renderInputs()
) : (
    <KeyboardAvoidingView behavior="padding">
        {this.renderInputs()}
    </KeyboardAvoidingView>
)}

I have used this method and I can assure that it works. If it is not working then there is a chance that you are missing something.

rule_it_subir
  • 650
  • 10
  • 12
  • 1
    You can use `KeyboardAvoidingView ` for Android as well. Just set `behavior="height"`. No need for a render function. – Pawel Nov 10 '22 at 22:00
10

Hooks version:

const [keyboardOffset, setKeyboardOffset] = useState(0);
const onKeyboardShow = event => setKeyboardOffset(event.endCoordinates.height);
const onKeyboardHide = () => setKeyboardOffset(0);
const keyboardDidShowListener = useRef();
const keyboardDidHideListener = useRef();

useEffect(() => {
  keyboardDidShowListener.current = Keyboard.addListener('keyboardWillShow', onKeyboardShow);
  keyboardDidHideListener.current = Keyboard.addListener('keyboardWillHide', onKeyboardHide);

  return () => {
    keyboardDidShowListener.current.remove();
    keyboardDidHideListener.current.remove();
  };
}, []);
Teodor Ciuraru
  • 3,417
  • 1
  • 32
  • 39
  • 1
  • 1
    In my case `keyboardDidShow` & `keyboardDidHide` event worked. – Muhammad Adeel Shoukat Sep 20 '21 at 10:21
  • For Typescript, you'll need to type the event and ref like so: const onKeyboardShow = (event: { endCoordinates: { height: React.SetStateAction } }) => setKeyboardOffset(event.endCoordinates.height); const onKeyboardHide = () => setKeyboardOffset(0); const keyboardDidShowListener = useRef(); const keyboardDidHideListener = useRef(); – airowe Aug 18 '22 at 14:39
6

you can use KeyboardAvoidingView as follows

if (Platform.OS === 'ios') {
        return <KeyboardAvoidingView behavior="padding">
            {this.renderChatInputSection()}
        </KeyboardAvoidingView>
    } else {
        return this.renderChatInputSection()
    }

Where this.renderChatInputSection() will return the view like textinput for typing message. Hope this will help you.

Maneesh
  • 664
  • 5
  • 12
2

For android you can set android:windowSoftInputMode="adjustResize" for Activity in AndroidManifest file, thus when the keyboard shows, your screen will resize and if you put the TextInput at the bottom of your screen, it will be keep above keyboard

SiSa
  • 2,594
  • 1
  • 15
  • 33
2

write these two lines in your android/app/src/main/AndroidManifest.xml inside activity tag

android:launchMode="singleTask" android:windowSoftInputMode="stateAlwaysHidden|adjustPan"

  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jul 03 '22 at 18:32
0

react-native-keyboard-aware-scroll-view caused similar issue in ios. That's when I came across react-native-keyboard-aware-view. Snippets are pretty much same.

    <KeyboardAwareView animated={true}>
        <View style={{flex: 1}}>
          <ScrollView style={{flex: 1}}>
              <Text style={{fontSize: 20, color: '#FFFFFF'}}>A</Text>
              <Text style={{fontSize: 20, color: '#FFFFFF'}}>B</Text>
              <Text style={{fontSize: 20, color: '#FFFFFF'}}>C</Text>
              <Text style={{fontSize: 20, color: '#FFFFFF'}}>D</Text>
          </ScrollView>
        </View>
        <TouchableOpacity style={{height: 50, backgroundColor: 'transparent', alignItems: 'center', justifyContent: 'center', alignSelf: 'stretch'}}>
          <Text style={{fontSize: 20, color: '#FFFFFF'}}>Submit</Text>
        </TouchableOpacity>
      </KeyboardAwareView>

Hope it hepls

HGK
  • 181
  • 9
0

You will definitely find this useful from

Keyboard aware scroll view Android issue

I really don't know why you have to add

"androidStatusBar": { "backgroundColor": "#000000" }

for KeyboardawareScrollview to work

Note:don't forget to restart the project without the last step it might not work enjoy!

Frankrnz
  • 694
  • 6
  • 5
0

I faced the same problem when I was working on my side project, and I solved it after tweaking KeyboardAvoidingView somewhat. I published my solution to npm, please give it a try and give me a feedback! Demo on iOS

Example Snippet

import React from 'react';
import { StyleSheet, TextInput } from 'react-native';
import KeyboardStickyView from 'rn-keyboard-sticky-view';

const KeyboardInput = (props) => {
  const [value, setValue] = React.useState('');

  return (
    <KeyboardStickyView style={styles.keyboardView}>
      <TextInput
        value={value}
        onChangeText={setValue}
        onSubmitEditing={() => alert(value)}
        placeholder="Write something..."
        style={styles.input}
      />
    </KeyboardStickyView>
  );
}

const styles = StyleSheet.create({
  keyboardView: { ... },
  input: { ... }
});

export default KeyboardInput;
0

I based my solution of @basbase solution.

My issue with his solution that it makes the TextInput jumps up without any regard for my overall view.

That wasn't what I wanted in my case, so I did as he suggested but with a small modification

Just give the parent View styling like this:

 <View 
             style={{
              flex: 1,
              bottom:   keyboardOffset,
          }}>

And it would work! the only issue is that if the keyboard is open and you scrolled down you would see the extra blank padding at the end of the screen.

RowanX
  • 1,272
  • 2
  • 14
  • 27
0

flexGrow: 1 is the key.

Use it like below:

<ScrollView contentContainerStyle={styles.container}>
  <TextInput
    label="Note"
    value={currentContact.note}
    onChangeText={(text) => setAttribute("note", text)}
  />
</ScrollView>
const styles = StyleSheet.create({
  container: {
    flexGrow: 1,
  },
});
Yuvraj Patil
  • 7,944
  • 5
  • 56
  • 56
0

install this package npm i react-native-keyboard-aware-scroll-view --save then put your input like this

`<KeyboardAwareScrollView>
  <View>
    <TextInput />
  </View>
</KeyboardAwareScrollView>`
0

Add "softwareKeyboardLayoutMode": "pan" to the app.json file under android:

"android": {
      "softwareKeyboardLayoutMode": "pan",
      "adaptiveIcon": {
        "foregroundImage": "./assets/adaptive-icon.png",
        "backgroundColor": "#ffffff"
      }
    },
0

This is worked for me Go to AndroidManifest.xml Paste the below line inside the activity tag

android:windowSoftInputMode="stateAlwaysHidden|adjustPan"
-1

Best and Easy Way is to use Scroll View , It will Automatically take content Up and TextInput will not be hide,Can refer Below Code

  <ScrollView style={styles.container}>
  <View>
    <View style={styles.commonView}>
      <Image source={firstNameIcon} style={{width: 25, height: 25}}></Image>
      <Text style={styles.commonTxt}>First Name</Text>
    </View>

    <TextInput
      onFocus={() => onFocus('firstName')}
      placeholder="First Name"
      style={styles.txtInput}
      onChangeText={(text) => onChangeText(text, 'firstName')}
      value={firstNameValue}
    />
  </View>
  <View>
    <View style={styles.commonView}>
      <Image source={LastNameIcon} style={{width: 25, height: 25}}></Image>
      <Text style={styles.commonTxt}>Last Name</Text>
    </View>

    <TextInput
      onFocus={() => onFocus('lastName')}
      placeholder="Last Name"
      style={styles.txtInput}
      onChangeText={(text) => onChangeText(text, 'lastName')}
      value={lastNameValue}
    />
  </View>
  <View>
    <View style={styles.commonView}>
      <Image source={callIcon} style={{width: 25, height: 25}}></Image>
      <Text style={styles.commonTxt}>Number</Text>
    </View>

    <TextInput
      onFocus={() => onFocus('number')}
      placeholder="Number"
      style={styles.txtInput}
      onChangeText={(text) => onChangeText(text, 'number')}
      value={numberValue}
    />
  </View>
  <View>
    <View style={styles.commonView}>
      <Image source={emailIcon} style={{width: 25, height: 25}}></Image>
      <Text style={styles.commonTxt}>Email</Text>
    </View>

    <TextInput
      onFocus={() => onFocus('email')}
      placeholder="Email"
      style={styles.txtInput}
      onChangeText={(text) => onChangeText(text, 'email')}
      value={emailValue}
    />
  </View>

  <View style={styles.viewSavebtn}>
    <TouchableOpacity style={styles.btn}>
      <Text style={styles.saveTxt}>Save</Text>
    </TouchableOpacity>
  </View>
</ScrollView>
-1

go to your Android>app>src>main> AndroidManifest.xml write these 2 lines :

android:launchMode="singleTop" android:windowSoftInputMode="adjustPan"

enter image description here

Atomract
  • 15
  • 1