KeyboardAvoidingView Shrinks My TextInputs No Matter What - javascript

No matter what I do, KeyboardAvoidingView shrinks my TextInputs as much as it can instead of adding padding to the content above them and pushing them off the screen.
All I want is the normal behavior where my content is padded off the screen and nothing shrinks as is seen in the simplest tutorials using this component. I've tried all the behaviors, and all kinds of permutations of view hierarchies. No matter what I do, it will shrink the inputs.
<KeyboardAvoidingView style={Styles.containerView} behavior={'padding'}>
<View style={Styles.topContainerView}>
<Image style={Styles.subLogo} source={require('../../../assets/images/app-icon.png')} />
<View style={{justifyContent: 'center', marginVertical: 10}}>
<Text style={Styles.subtext}>{subtext}</Text>
</View>
<TextInput
style={Styles.textInput}
onChangeText={(text) => this.setState({firstName: text})}
value={this.state.firstName}
/>
<TextInput
style={Styles.textInput}
onChangeText={(text) => this.setState({lastName: text})}
value={this.state.lastName}
placeholderText={'Last Name'}
/>
<TextInput
style={Styles.textInput}
onChangeText={(text) => this.setState({email: text})}
value={this.state.email}
placeholderText={'Enter Email'}
/>
<TextInput
style={Styles.textInput}
onChangeText={(text) => this.setState({password: text})}
value={this.state.password}
placeholderText={'Enter Password'}
secureTextEntry={true}
/>
<TextInput
style={Styles.textInput}
onChangeText={(text) => this.setState({confirmPassword: text})}
value={this.state.confirmPassword}
placeholderText={'Confirm Password'}
secureTextEntry={true}
/>
</View>
<View style={Styles.bottomContainerView}>
<Button buttonStyle={Styles.continueButton} text={"Continue"} onPress={continueAction} />
<TouchableOpacity style={Styles.cancelContainer} onPress={this.goBack}>
<Text style={Styles.cancelText}>{'Cancel'}</Text>
</TouchableOpacity>
</View>
</KeyboardAvoidingView>
In my code above, the Image element and subtext below it will not budge. No padding will be added to them nor will they shrink. Instead, the TextInputs will all shrink.
I just want them to be pushed off the screen instead of the inputs shrinking.
I have also tried adding a ScrollView within the KeyboardAvoidingView that contains all the elements, and even given a hard-coded height to the inputs.

When working with RN 0.63.1 and Android 9, I encountered the same issue. Upon reading GitHub issues, using KeyboardAvoidingView was discouraged and instead setting this in my AndroidManifest.xml fixed it.
Default:
<activity
...
android:windowSoftInputMode="adjustResize"
>
Change it to:
<activity
...
android:windowSoftInputMode="adjustPan"
>
I found setting this makes the padding work but it is still too close to the keyboard. I used KeyboardAvoidingView to add some padding between keyboard and text input.

Related

Android keyboard overlapping inputs

Using KeyboardAvoidingView I have a basic example where I would like the keyboard to push the inputs upwards so it is not overlapping on Android. The inputs do not move when the keyboard is in focus. Any ideas?
The inputs stay in a fixed position, do I need to place everything in a scroll view?
UPDATE: I use nested navigators, could a style on a parent component prevent this working?
<KeyboardAvoidingView behavior="padding" style={{ flex: 1 }}>
<TextInput placeholder="input1" />
<TextInput placeholder="input2" />
<TextInput placeholder="input3" />
<TextInput placeholder="input4" />
<TextInput placeholder="input5" />
<TextInput placeholder="input6" />
<TextInput placeholder="input7" />
<TextInput placeholder="input8" />
<TextInput placeholder="input9" />
<TextInput placeholder="input10" />
<TextInput placeholder="input11" />
<TextInput placeholder="input12" />
</KeyboardAvoidingView>
try to change the behavior to height for android as described on keyboardavoidingview
import { KeyboardAvoidingView, Platform } from 'react-native';
<KeyboardAvoidingView behavior={Platform.OS == "ios" ? "padding" : "height"}
style={{ flex: 1 }} >

react native unfocus TextInput

I want to make a search bar in react-native like that :
If I click on icon, I focus on textInput, but if I click on other part of screen, unfocus the textInput.
The focus part is working with the ref, but I don't know if it's possible to unfocus the textinput when I click in other part of the screen.
<TextInput
multiline={false}
onChangeText={(text) => onChangeText(text)}
placeholder="search"
style={styles.textInput}
value={value}
ref={research}
></TextInput>
<TouchableOpacity onPress={()=>research.current.focus()}>
<Ionicons name="md-search" size={24} ></Ionicons>
</TouchableOpacity>
You could just dismiss the keyboard
import {Keyboard} from 'react-native'
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<View style={{flex: 1}}>
[your code in here]
</View>
</TouchableWithoutFeedback>

React Natvie buttons and textInput not working

Since the <Modal> in React Native is kinda iffy, I've made my own with a <View> that renders when this.state.display is true. But the text input and button doesn't do anything when clicked / interacted with.
I've tried using a regular <Modal> but prefer my way. As well as changing the actual style of the modal. I've added different onPresses and a few other minor code adjustments that haven't worked.
shouldRender() {
if (this.state.display) {
return (
<View style={styles.modal}>
<TextInput
placeholder="Event Title"
onChangeText={title => this.setState({title})}
value={this.state.title}
style={styles.textInput}
/>
<TextInput />
<Button />
<Button /> //the other buttons and textinput has similar things
</View>
);
} else {
return <View></View>;
}
}
In the render method:
return(
<TouchableOpacity
onPress={this.addReminder}
style={styles.reminderTouch}>
<Text style={styles.reminderBtn}>+</Text>
</TouchableOpacity>
)
And the addReminder method just sets this.state.display to true
I'm looking for the buttons to submit / close the modal and the text input to change the title and text state. Right now, the buttons don't animate on press and the text inputs can't be clicked.
Also, prior to the modal, when the textinputs where just on screen, everything worked fine.
Your description sounds like an issue with zIndex - something is being rendered over top of your modal if the button opacity and input focus are not working.
I would try moving the <View>{this.shouldRender()}</View> to be the final child in the containing <View> in your render method and if that doesn't work then up the zIndex.
You can do something like this inside your render()
render(){
return(
<Modal visible={this.state.display} style={styles.modal}>
<TextInput
placeholder="Event Title"
onChangeText={title => this.setState({title})}
value={this.state.title}
style={styles.textInput}
/>
<TextInput />
<Button />
<Button /> //the other buttons and textinput has similar things
</Modal>
<TouchableOpacity
onPress={this.setState({display: true})}
style={styles.reminderTouch}>
<Text style={styles.reminderBtn}>+</Text>
</TouchableOpacity>
)
}
this modal will only display if this.state.disaply == true

KeyboardAvoidingView not working with Expo

I cannot seem to get the keyboard to push the content up in my React-Native Expo app. I am testing this from the expo App by publishing it from my development machine.
Try as I might, nothing seems to push the view up when the keyboard comes into focus, is there a specific order of components, or some property I am missing; I have included the versions, the render block and the style blocks I think which are relevant.
I am using the following versions (latest);
"expo": "^29.0.0",
"react": "16.3.1",
"react-native": "https://github.com/expo/react-native/archive/sdk-29.0.0.tar.gz",
For the login page, the render code looks like the following;
render() {
return (
<SafeAreaView style={styles.flexContainer}>
<KeyboardAvoidingView
style={styles.flexContainer}
behavior="padding"
>
<Image style={styles.image} source={require('../../assets/images/backgroundWelcome.png')} role="presentation" />
<View style={styles.container}>
<View style={[styles.row, styles.border]}>
<TextInput
placeholder='Email'
style={styles.input}
onChangeText={(input) => this.setState({email: input})}
value={this.state.email}
/>
</View>
<View style={[styles.row, styles.border]}>
<TextInput
placeholder='Password'
style={styles.input}
secureTextEntry={true}
onChangeText={(input) => this.setState({password: input})}
value={this.state.password}
/>
</View>
<View style={styles.row}>
<StyledButton callback={this.handleLogin} title='Log In'/>
</View>
</View>
</KeyboardAvoidingView>
</SafeAreaView>
)
}
These are the styles that are relevant;
root: {
flex: 1,
alignItems: 'center',
backgroundColor: '#fff',
},
flexContainer: {
flex: 1,
},
container: {
paddingHorizontal: 40,
paddingBottom: 22,
alignItems: 'center',
flex: -1
},
row: {
flexDirection: 'row',
marginVertical: 10,
},
I ultimately could not find a full solution to the above directly, but I did find a npm module called.
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
I then nested this inside a ScrollView and included the View and Form inside it.
<ScrollView
<KeyboardAwareScrollView>
<View>
<!-- stuff -->
<View
<KeyboardAwareScrollView>
<ScrollView>
The module can be found here;
react-native-keyboard-aware-scroll-view
At the time of writing appears a very popular module with ~30k downloads a week. I have no affiliation to this module, but it works for me.
I had the same issue adding flex: 1 to KeyboardAvoidingView fixed my problem:
<KeyboardAvoidingView style={{ flex: 1 }} behavior={"padding"} >
<ScrollView >
<Card>
<CardItem header bordered>
<Text>Personal Information</Text>
</CardItem>
<CardItem bordered>
<Body>
<Item floatingLabel style={styles.item}>
<Label>Full Name</Label>
<Input />
</Item>
<Item floatingLabel style={styles.item}>
<Label>Headline</Label>
<Input />
</Item>
<Item floatingLabel style={styles.item}>
<Label>Location</Label>
<Input />
</Item>
<Item floatingLabel style={styles.item}>
<Label>Email</Label>
<Input />
</Item>
<Item floatingLabel style={styles.item}>
<Label>Phone Number</Label>
<Input />
</Item>
<Item floatingLabel style={styles.item}>
<Label>Phone Number</Label>
<Input />
</Item>
<Item floatingLabel style={styles.item}>
<Label>Phone Number</Label>
<Input />
</Item>
</Body>
</CardItem>
</Card>
<ListItem>
<Left>
<Text>Make my Profile Public</Text>
</Left>
<Right>
<Switch value={this.state.publicProfileRadioValue}
onValueChange={(value) => this.setState({ publicProfileRadioValue: value })}
/>
</Right>
</ListItem>
</ScrollView>
</KeyboardAvoidingView>
Add minHeight property to the root view style.
<KeyboardAvoidingView
behavior={Platform.OS == 'ios' ? 'padding' : 'height'}
style={styles.container}>
{//content }
</KeyboardAvoidingView>
minHeight: Math.round(Dimensions.get('window').height),
Do not forget to import Dimensions form react native
import { Dimensions } from 'react-native';
for anyone else who ran into this when testing on Android, make sure the element you want to be keyboard avoided also has flex: 1.
this will not work:
<KeyboardAvoidingView
behavior={Platform.OS == "ios" ? "padding" : "height"}
style={{ flex: 1 }}
>
<TextInput style={{ height: 300 }} />
</KeyboardAvoidingView>
this will:
<KeyboardAvoidingView
behavior={Platform.OS == "ios" ? "padding" : "height"}
style={{ flex: 1 }}
>
<TextInput style={{ flex: 1 }} />
</KeyboardAvoidingView>
without flex 1, the target element will not resize its height accordingly to avoid the keyboard
I could achieve the right behavior with this implementation:
Removed KeyboardAvoidingView component.
Added this to the app.json file:
"android": {
"softwareKeyboardLayoutMode": "pan"
}
Hope it works for you guys as well!

Can't style my checkbox as `alignSelf: 'flex-end'` or `right: 0`

I can't style my checkbox as alignSelf: 'flex-end' or right: 0.
I want to put the checkbox top and right but there is weird padding on the photo. I tried many different styles but none of them works. :(
This is FlatList's renderItem()
<TouchableWithoutFeedback
style={{flex:1}}
onPress={() => this._handleImagePress(item.id, item.outfit_img)}>
<View style={{flex: 1}}>
<Image
key={item.id}
source={{uri: item.outfit_img}}
style={styles.rowImage}
resizeMode="cover"
/>
<CheckBox checked={isSelected} style={{marginLeft:2, marginTop:2, position:'absolute', alignSelf: 'flex-end'}}/>
</View>
</TouchableWithoutFeedback>
Here is FlatList function
render() {
return (
<View style={styles.root}>
<FlatList
data={this.props.outfits}
extraData={this.state.selectedStyles}
keyExtractor={this._keyExtractor}
renderItem={this._renderItem}
numColumns={3}
renderHeader={this._renderHeader}/>
</View>
);
}
UPDATE FIX I guess Native-Base Checkbox is terrible on styling. This is working version. Any optimization? or better option?
<TouchableWithoutFeedback
style={{flex:1}}
onPress={() => this._handleImagePress(item.id, item.outfit_img)}>
<View style={styles.rowImage}>
<Image
key={item.id}
source={{uri: item.outfit_img}}
style={styles.rowImage}
resizeMode="cover"
/>
<View style={{height:32, width:32, position:'absolute', top:0, right:0, marginTop:4, paddingRight:12}}>
<CheckBox checked={isSelected} color="#f64e59"/>
</View>
</View>
</TouchableWithoutFeedback>
I have created a snack here https://snack.expo.io/HJYNoAEAW , hopefully you are expecting this behaviour.
Absolutely positioned children of the flex container are not flex items anymore and therefore don't obey flex alignment properties (align-* and justify-*). They do obey offset keywords (left, right, etc.), but these offsets are calculated relatively to the closest positioned ancestor (or, if there is none, to the root element). Try adding position:'relative' to your TouchableWithoutFeedback element's style attribute to make it the nearest positioned ancestor of the checkbox, so it could be positioned relatively to it.
Remove position: absolute from the CheckBox instead add justify-content: space-between to the parent of the element.

Categories