react-native
react-native copied to clipboard
KeyboardAvoidingView has no effect on multiline TextInput
KeyboardAvoidingView only works with single-line TextInputs. When the multiline
prop is set, KeyboardAvoidingView does not shift the TextInput at all.
Is this a bug report?
Yes
Have you read the Contributing Guidelines?
Yes
Environment
Environment: OS: macOS Sierra 10.12.6 Node: 7.0.0 npm: 3.10.8 Watchman: 4.7.0 Xcode: 9.1
Packages: (wanted => installed) react-native: 0.49.3 react: 16.0.0-beta.5
Target Platform: iOS (10.3)
Steps to Reproduce
- Use a
<TextInput>
component withmultiline
prop set. - Wrap this in a ScrollView
- Wrap that in a KeyboardAvoidingView.
Expected Behavior
Multiline TextInput should scroll above the soft keyboard.
Actual Behavior
Soft keyboard covers multiline TextInput.
Reproducible Demo
import React, { Component } from 'react';
import { Text, TextInput, View, ScrollView, KeyboardAvoidingView, Keyboard} from 'react-native';
...
render() {
return (
<KeyboardAvoidingView style={{flex:1}} behavior="padding" keyboardVerticalOffset={64}>
<ScrollView keyboardShouldPersistTaps={'handled'}>
<View style={{padding: 12}}>
// various content to fill the page
<Text style={{fontSize: 20, padding: 40}}>MESSAGE 1</Text>
<Text style={{fontSize: 20, padding: 40}}>MESSAGE 2</Text>
<Text style={{fontSize: 20, padding: 40}}>MESSAGE 3</Text>
<Text style={{fontSize: 20, padding: 40}}>MESSAGE 4</Text>
<Text style={{fontSize: 20, padding: 40}}>MESSAGE 5</Text>
<Text style={{fontSize: 20, padding: 40}}>MESSAGE 6</Text>
<Text style={{fontSize: 20, padding: 40}}>MESSAGE 7</Text>
<Text style={{fontSize: 20, padding: 40}}>MESSAGE 8</Text>
<Text style={{fontSize: 20, padding: 40}}>MESSAGE 9</Text>
<Text style={{fontSize: 20, padding: 40}}>MESSAGE 10</Text>
</View>
<TextInput
style={{padding: 4}}
multiline={true}
placeholder={'Type something here...'}
onChangeText={this.updateMessage}
value={this.state.message}
/>
</ScrollView>
</KeyboardAvoidingView>
);
}
I have a similar issue
Environment
node: 8.9.1 react: 16.0.0 react-native: 0.50.3 yarn: 1.3.2 watchman: 4.9.0 xcode: 9.1
Steps to Reproduce
- Use a
<TextInput>
component withautoCorrect="false"
prop. - Wrap that in a KeyboardAvoidingView with
behavior="position"
prop. - Change keyboard type to Emoji keyboard
Expected Behavior
Multiline TextInput should be above the soft keyboard.
Actual Behavior
Soft keyboard covers TextInput.
Reproducible Demo
https://github.com/vivalaakam/react-native-issue
Keyboard.addListener('keyboardWillChangeFrame', this.onKeyboardChange)
doesn't`t fire when I change keyboard to emoji and fires when I change from emoji to other
KeyboardAvoidingView works fine with multiline TextInput because i am using them myself. Initially they would not work for me. To solve my problem i removed the height on the TextInput and set the behavior to "padding". The "flex: 1" you have on the KeyboardAvoidingView might be the problem i think or its the scrollview. But KeyboardAvoidingView definitely works fine with multiline.
Referring to my snippet posted above, there's no height on the TextInput, and KeyboardAvoidingView's behavior is set to padding.
Its style needs flex:1
to allow the ScrollView to take up the entire height.
Try the code with and without multiline set. It fails with multiline set, but the same code works for single line TextInputs.
Same problem here!
@peacechen I have exactly the same problem like you. Need to add flex: 1 for the ScrollView as the wrapper. And it works if I remove the prop multiline={true}. Any solution for this?
The same issue。 my code is same as the author. there is a multiline TextInput in ScrollView. outsider with a KeyboardAvoidingView wrapper.
If anyone still is looking for a fix, you could try
<View style={{position:relative}}>
<TextInput ref='multilineText' value={this.state.textValue}
onChangeText={(textValue) => this.setState({textValue})}/>
<TextInput style={{ color:'transparent', position: 'absolute', width: '100%', height: '100%' }}
placeholderTextColor='transparent'
onFocus={() => setTimeout(() => this.refs.multilineText.focus(), 1000) }
value={this.state.textValue}
onChangeText={(textValue) => this.setState({textValue})}
/>
</View>
Its a dirty hack but it does the job, what it does it when user clicks on the input it would be clicking on the single line and the keyboard will scroll to that line then after 1 seconds (you can adjust this, i just found 1 seconds to be good with our app) it would focus on the multiline. The value and onChangeText makes sure that when the user star typing they would have the same value except the single line has transparent text.
The downside is when a user clicked the multiple line, the cursor wont go to the location they clicked but it would go to the end.
@monmonja That's a creative work-around. I wonder if it could also be done by setting the multiline
prop to a state variable that is changed during onFocus
. That would eliminate the second TextInput
.
I don't see the multiline prop in the first TextInput, but I assume it's supposed to be in there.
Has anyone found a good solution for this?
@peacechen I tried to implement your suggestion but it has a strange effect and doesn't work. Something's flickering and the keyboard eventually disappears. I am also looking for a solution to this. Cannot apply @monmonja 's workaround because I'm using redux-form. This makes it much more complicated for this workaround. I can confirm that all is working fine when I remove the multiline prop. I wrapped the whole application with KeyboardAvoidingView and my multiline TextInput is at the end of the form like in the author's example. I have no height applied to the TextInput which in a few cases can cause issues. I am using react-native: 0.53.0
same problem here and still have no solution
I too facing the same issue. It works fine if multiline is set to false and not if set to true. My TextInput does not have any height. Any solutions??
A workaround for this is to make a reference to the parent scrollview and call its scrollTo method to the multilined TextInput coordinates whenever onFocus is called.
<KeyboardAvoidingView
style={{ flex: 1 }}
behavior="padding"
>
<ScrollView ref={component => { this.myScrollView = component; }}>
<TextInput
multiline
onFocus={() => this.myScrollView.scrollTo({ x: 0, y: 750, animated: true })} // <- your coordinates here
/>
</ScrollView>
</KeyboardAvoidingView>
same problem here only on IOS textinput multiline has no effect on keyboardavoidingview
it is working fine on android
This has been quite frustrating for us as well.. Seems like the only consistent way to do this is by scrolling manually as @jasonchoibiz suggested.
It's an ugly workaround though! ☹️
there is news about this problem?
Still having this. Tried the suggested solutions.
same problem here
Same issue, here's a simple snack for anyone to play with: https://snack.expo.io/r1qpj0k5Q
Same issue, here's a simple snack for anyone to play with: https://snack.expo.io/r1qpj0k5Q
I've tried this and it works:
react-native version 0.56.1 same problem....
it is working;
<KeyboardAvoidingView behavior="padding" style={Platform.OS !== 'android' && { flex: 1 }}>
<ScrollView>
...
<TextInput ... />
...
</ScrollView>
</KeyboardAvoidingView>
@recepkoseoglu It works on non-multiline Inputs. Try on multiline.
It's working if we use <View>
to wrap the content instead of <ScrollView>
, not ideal if you have many TextInputs though.
<KeyboardAvoidingView
behavior={Platform.OS === "ios" ? "padding" : null}
style={{ flex: 1 }}
>
<View style={{ flex: 1, justifyContent: "flex-end" }}>
...
<TextInput multiline />
<View style={{ flex: 1 }} /> // Use this to take up bottom spacing
</View>
</KeyboardAvoidingView>
No fix yet?
RN 0.57... confirm same issue.
still same issue here. any solution?
I switched to "React-Native Keyboard Manager" and it works. Just install and your issues are solved
This is really causing a lot of problems. Any updates on this issue? I have tried using the libraries mentioned above but each of them come with sacrifices in user experience.