(I'm testing on Android if it matters)
I'm using the component KeyboardAwareScrollView to make the inputs visible while the soft keyboard is open. I have two inputs, one below the other, and when I press the top one, the soft keyboard does make sure it's visible but also hides the one below.
Is there a way to make sure that when the keyboard is open, the two inputs will remain visible, even if the user pressed the one at the top?
My code:
<KeyboardAwareScrollView scrollEnabled={false} resetScrollToCoords={{ x: 0, y: 0 }}>
<Image {...this.image.header} style={{ height: 400, width: '100%' }} />
<View>
<TextInput style={{ backgroundColor: 'red' }} />
<TextInput style={{ backgroundColor: 'blue' }} />
</View>
</KeyboardAwareScrollView>
I am copying this answer of boredgames.
<TextInput
placeholder = "FirstTextInput"
returnKeyType = { "next" }
onSubmitEditing={() => { this.secondTextInput.focus(); }}
blurOnSubmit={false}
/>
<TextInput
ref={(input) => { this.secondTextInput = input; }}
placeholder = "secondTextInput"
/>
Related
If I have another text input on the same screen with react-native-gifted-chat component, the keyboard won't work correctly. It will appear in a sec then be dismissed immediately. Happens on both Android and IOS, physical devices and emulator.
I handled keyboard by myself, inside a KeyboardAvoidingView
Demo:
Here my code
<View style={styles.container}>
<View style={styles.container}>
{renderVideo()}
<KeyboardAvoidingView
behavior={Platform.OS === "ios" ? "padding" : undefined}
style={{ flex: 1, justifyContent: "flex-end" }}
>
<View style={{ height: 350 }}>
<GiftedChat
textInputProps={{ onFocus: onFocusHandler, onBlur: onBlurHandler }} //
isKeyboardInternallyHandled={false}
wrapInSafeArea={false}
keyboardShouldPersistTaps="handled"
onSend={onSendMessage}
alwaysShowSend
messages={messages}
infiniteScroll
scrollToBottom={false}
inverted
/>
</View>
</KeyboardAvoidingView>
</View>
<AlertModal ref={alertRef} /> // This modal contain another input
</View>
Need some help making Keyboard for second text input works fine
Displaying more than 200+ images in the flatlist and make the user to select or deselect by clicking an image. So, when the user is clicks a image, Need to show the check-circle icon on the image. Similarly, when the user is deselect the selected image, need to remove the icon. I got two arrays images[] and selectedImagesId[]. Whenever the user selects an image, the image id will be pushed into selectedImagesId array. By the way, Iam showing the icon if the rendered image id avaliable in the selectedImagesId. The problem here is, it takes so long to display or remove the icon.
<FlatList
data={props.images}
extraData={selectedImagesId}
initialNumToRender={10}
refreshing={true}
removeClippedSubviews={true}
maxToRenderPerBatch={1}
windowSize={7}
showsVerticalScrollIndicator={false}
numColumns={3}
keyExtractor={(item) => item.id.toString()}
renderItem={(itemData) => <RenderData itemData={itemData} />}
>
const RenderData = ({ itemData }) => (
<View>
<TouchableOpacity
activeOpacity={0.8}
style={{
width: width / 3.5,
height: height / 7,
padding: 2,
}}
onPress={() => {
console.log('pressed');
if (props.selectedImages.includes(itemData.item.uri)) {
const index = props.selectedImages.indexOf(itemData.item.uri);
if (index > -1) {
props.removeImageandId(index, itemData.item.id);
}
} else {
props.selectImageandId(itemData.item.uri, itemData.item.id);
}
}}>
<Image
style={{ width: '100%', height: '100%' }}
source={{
uri: itemData.item.uri,
}}
/>
{selectedImagesId.includes(itemData.item.id) && (
<AntDesign
name='checkcircle'
size={24}
color='white'
style={{ position: 'absolute', bottom: 5, right: 15 }}
/>
)}
</TouchableOpacity>
<Text style={{ backgroundColor: 'red', fontSize: 25 }}>
{render.current++}
</Text>
</View>
);
You can Refer This article
It will guide you on how to render Only particular selected components that change.
not the Whole flatList components.
so, that based Only selected particular component you can remove the icon. not whole flatList Re-render.
I've been trying to get my TextInput to focus (open keyboard) when I tap anywhere within the (gray) multiline box, but it is only detecting taps on lines with text (or the placeholder).
Is there any way to force the TextInput to focus when I click anywhere on the gray area?
<ScrollView style={{ flex: 1}}>
<View style = {Style.dropdownField}>
<Dropdown
label={'Motivo'}
data={this.props.remiseExcusesData}
value={this.state.remiseExcuses.value}
onChangeText={(value,index, data)=> this.setState({remiseExcuses:data[index]})}
/>
</View>
<View style = {{ height:150, marginHorizontal:20, backgroundColor:'#f9f9f9', marginTop:20}}>
<TextInput
style={Style.minitextInput}
placeholder={'Escribir motivo'}
textAlign={'left'}
autoCorrect={false}
autoCapitalize={'none'}
underlineColorAndroid='transparent'
multiline
onChangeText={(text) => this.setState({motive:text}) }
value={this.state.motive}
onFocus={() => console.log('Fire only on tap')}
/>
</View>
</ScrollView>
You can use this for handle the focus of gray box.
<TouchableOpacity style = {{ height:150, marginHorizontal:20, backgroundColor:'#f9f9f9', marginTop:20}} onPress={this.onPressGrayBox}>
<TextInput
ref="textInput"
style={{ height: 150, textAlignVertical: 'top' }}
placeholder={'Escribir motivo'}
textAlign={'left'}
autoCorrect={false}
autoCapitalize={'none'}
underlineColorAndroid='transparent'
multiline
onChangeText={(text) => this.setState({motive:text}) }
value={this.state.motive}
/>
</TouchableOpacity>
declare the method to handle the action, this will help to set textinput focus automatically.
onPressGrayBox=()=>{
this.refs.textInput.focus()
}
This steps helps me, please use
You can handle something like
<View style = {{ height:150, marginHorizontal:20, backgroundColor:'#f9f9f9', marginTop:20}}>
<TextInput
style={{ height: 150, textAlignVertical: 'top' }}
placeholder={'Escribir motivo'}
textAlign={'left'}
autoCorrect={false}
autoCapitalize={'none'}
underlineColorAndroid='transparent'
multiline
onChangeText={(text) => this.setState({motive:text}) }
value={this.state.motive}
onFocus={() => console.log('Fire only on tap')}
/>
</View>
I've been tackling this issue for a few weeks, and it's driving me insane.
Basically, I have a Modal component that nests a form. The form is a bunch of TextInput components, at the heart of everything. One of the components in the form is an Autocomplete, from React Native Autocomplete Input. The problem is that I'm able to put the results list from Autocomplete in front of everything else, but my touches pass right through the container and focuses on the TextInput behind the results list. I'm not able to change the order of components, so I can't just put this one input after everything else.
The general setup of the form is below:
<Modal>
<TouchableWithoutFeedback>
<View style={containerStyle}>
<TouchableWithoutFeedback>
<View>
<CardSection style={sectionStyle}>
<Input
...props...
/>
</CardSection>
<CardSection style={acSectionStyle}>
<Text style={labelStyle}>Brand *</Text>
<View style={acContainerStyle}>
<Autocomplete
autoCapitalize='none'
autoCorrect={false}
listStyle={acListStyle}
data={brands.length === 1 && comp(query, brands[0]) ? [] : brands}
defaultValue={query}
onChangeText={text => this.setState({ query: text })}
renderItem={this.renderItem.bind(this)}
hideResults={this.state.hideResults ? this.state.hideResults : undefined}
onBlur={() => this.setState({ hideResults: true })}
onFocus={() => this.setState({ hideResults: false })}
/>
</View>
</CardSection>
<CardSection style={sectionStyle}>
<Input
...props...
/>
</CardSection>
</View>
</TouchableWithoutFeedback>
</View>
</TouchableWithoutFeedback>
</Modal>
I had to stack the TouchableWithoutFeedback components in order to make the modal behave. There's more props in the components, but I only kept what was relevant.
My renderItem method is:
renderItem(brand) {
return (
<TouchableOpacity
style={{ width: '100%', height: 25 }}
onPress={() => {
this.setState({ pBrand: brand.trim(), query: brand.trim() });
}}
>
<Text style={styles.listItemStyle}>{brand}</Text>
</TouchableOpacity>
);
}
I don't believe it's a styling issue, but I've added the styles that deal with zIndex just in case:
containerStyle: {
backgroundColor: 'rgba(0, 0, 0, 0.75)',
position: 'relative',
flex: 1,
justifyContent: 'center',
zIndex: 1
},
acSectionStyle: {
justifyContent: 'center',
zIndex: 2,
height: 40
},
acContainerStyle: {
right: 0,
width: '75%',
flex: 1,
position: 'absolute',
zIndex: 2
}
The default keyboardShouldPersistTaps for Autocomplete is always. All of the questions I've seen suggest to set a higher zIndex (which isn't a problem - I can see the list, but if I tap on it, the tap goes through to the TextInput behind it), change the order of components (which I can't do), set onStartShouldSetResponderCapture to true (which didn't work), or mess with Pointer Events, none of which worked.
I'm using React Native V0.57.1, an actual Android device, and the project is built with Expo.
Finally, I've recorded a small demo for what my problem is. When the cursor re-appears, that's when I clicked on a result.
Is there just something I'm missing? I've only been writing in React Native for a few months so that's a definite possibility. I come from a web development background, so I thought that if a component was on top (thanks to zIndex), I'd be able to tap on it and not through it by default.
Edit: While messing around, if I change acSectionStyle to a height big enough for the dropdown, then the dropdown works how it should. The issue comes in when a sibling CardSection is being covered. The other CardSection takes precedence.
So, I finally found a workaround. Whether it's correct or not, which I feel like it isn't, at least it works!
I ended up taking the Autocomplete component (along with its' view) outside of the CardSection, but leaving the label in it, like so:
<CardSection style={acSectionStyle}>
<Text style={labelStyle}>Brand *</Text>
</CardSection>
<View style={acContainerStyle}>
<Autocomplete
autoCorrect={false}
listStyle={acListStyle}
// Text input container
inputContainerStyle={acTextContainerStyle}
style={acTextStyle}
placeholder='China Glaze'
data={brands.length === 1 && comp(query, brands[0]) ? [] : brands}
defaultValue={query}
onChangeText={text => this.setState({ query: text })}
renderItem={this.renderItem.bind(this)}
hideResults={this.state.hideResults ? this.state.hideResults : undefined}
onBlur={() => this.setState({ hideResults: true })}
onFocus={() => this.setState({ hideResults: false })}
/>
</View>
Then, and this is the part I think is wrong, I just played with the absolute-positioned view until I moved it far enough down to line up next to the label:
labelStyle: {
fontSize: 18,
paddingLeft: 20,
flex: 1
},
acContainerStyle: {
right: 0,
top: 102,
width: '72%',
flex: 1,
position: 'absolute',
zIndex: 10
}
I would love if someone has a better solution, but this is the best I could come up with. I try to avoid moving views with hard coded values just for scaling purposes, but it seems like this is the only option.
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]
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>;
}
}
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.
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();
};
}, []);
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.
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.
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
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
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!
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;
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.
android:launchMode="singleTask"
android:windowSoftInputMode="stateAlwaysHidden|adjustPan"
write these two lines in your android/app/src/main/AndroidManifest.xml
in activity tag
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,
},
});
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>
go to your Android>app>src>main> AndroidManifest.xml
write these 2 lines :
android:launchMode="singleTop" android:windowSoftInputMode="adjustPan"