Layout overlapping on text input in react native as you can see in the images.
I have experimented with keyboardAvoidingView and keyboardAwareScrollView but I just cant fix it or I am implementing them incorrectly.
How to avoid keyboard from changing your flex layout? What's the industry standard? keyboardAvoidingView? I find that inconsistent or have not understood it conceptually. My approach usually is wrapping the entire code with either keyboardAwareScrollView or keyboardAvoidingView. Do I only do it over the textInput component?
const InterviewAlignment = ({navigation}) => {
return (
<View style={styles.container}>
<View style={styles.header}>
</View>
<View style={styles.main}>
<View
style={{
flex: 1,
justifyContent: 'space-between',
}}>
<View
style={{
flex: 1,
backgroundColor: 'red',
}}>
</View>
<View style={styles.modeContainer}>
</View>
<View style={{flex: 1}}>
<Text style={styles.text}>Link Address</Text>
<TextInput
style={styles.linkInput}
/>
</View>
</View>
<View style={{flex: 1, backgroundColor: 'red'}}>
</View>
<View style={{flex: 1.5, backgroundColor: 'black'}}>
</View>
</View>
</View>
);
};
//RFValue is just a responsive wrapper
const styles = StyleSheet.create({
container: {
flex: 1,
},
header: {
flexDirection: 'row',
alignItems: 'center',
paddingHorizontal: RFValue(16),
minHeight: RFValue(56),
backgroundColor: '#B1C59B',
},
text: {
fontSize: RFValue(15),
color: 'black',
},
main: {
flex: 1,
padding: 15,
},
modeContainer: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'flex-start',
flex: 1,
backgroundColor: 'yellow',
},
linkInput: {
marginHorizontal: RFValue(40),
padding: 0,
paddingTop: 2,
borderBottomWidth: RFValue(1),
borderBottomColor: '#C4C4C4',
},
});
You can set height instead of flex in styling
Related
I'm currently developing an app to be used in an Android tablet, unfortunately I got comfortable and added too many features in web view before testing again on android and now they look quite different.
I have a few elements in a flex-box view with flex-direction 'row', this is how they look on the browser and how they should look:
Then the same app on android looks like this:
You can see the two lines with inputs without proper height to fit the text, and a third line on the bottom already from another input.
This is the component code (I removed one input line to make it simpler):
<View>
<Text style={styles.header}>
{LanguageService(language).form.personalData}:
</Text>
<View style={styles.twoColumns}>
<View style={styles.inputWrapper}>
<Text>
{LanguageService(language).form.firstName}:
</Text>
<TextInput
style={styles.input}
onChangeText={formikProps.handleChange('firstName')}
value={formikProps.values.firstName}
maxLength={20}
/>
</View>
<View style={styles.inputWrapper}>
<Text>
{LanguageService(language).form.phone}:
</Text>
<TextInput
style={styles.input}
onChangeText={formikProps.handleChange('phoneNumber')}
value={formikProps.values.phoneNumber}
keyboardType='phone-pad'
maxLength={15}
/>
</View>
</View>
</View>
And here is the style:
const styles = StyleSheet.create({
twoColumns: {
flex: 1,
flexDirection: 'row',
justifyContent: 'space-between',
},
inputWrapper: {
width: '48%',
flexDirection: 'row',
justifyContent: 'space-around',
borderBottomWidth: 1,
borderBottomColor: 'black',
margin: 10,
},
input: {
flexGrow: 1,
paddingLeft: 5,
},
header: {
color: 'red',
fontWeight: 'bold',
fontSize: 22,
},
}
I think you can achieve the shape in the first image with this structure:
<View style={styles.container}>
<View style={styles.headerContainer}>
<Text style={styles.header}>
{LanguageService(language).form.personalData}:
</Text>
</View>
<View style={styles.inputsContainer}>
<View stlye={styles.leftContainer>
<View style={styles.inputWrapper}>
<Text>
{LanguageService(language).form.firstName}:
</Text>
<TextInput
style={styles.input}
onChangeText={formikProps.handleChange('firstName')}
value={formikProps.values.firstName}
maxLength={20}
/>
</View>
</View>
<View stlye={styles.rightContainer>
<View style={styles.inputWrapper}>
<Text>
{LanguageService(language).form.phone}:
</Text>
<TextInput
style={styles.input}
onChangeText={formikProps.handleChange('phoneNumber')}
value={formikProps.values.phoneNumber}
keyboardType='phone-pad'
maxLength={15}
/>
</View>
</View>
</View>
</View>
Style:
const styles = StyleSheet.create({
container: {
display: 'flex',
flexDirection: 'column'
},
headerContainer: {
flex: 0.5
},
inputsContainer: {
flex: 1,
display: 'flex',
flexDirection: 'row'
},
leftContainer: {
flex: 1
},
rightContainer: {
flex: 1
}
inputWrapper: {
width: '48%',
flexDirection: 'row',
justifyContent: 'space-around',
borderBottomWidth: 1,
borderBottomColor: 'black',
margin: 10,
},
input: {
flexGrow: 1,
paddingLeft: 5,
},
header: {
color: 'red',
fontWeight: 'bold',
fontSize: 22,
},
}
I manage to solve this by removing the following line:
const styles = StyleSheet.create({
twoColumns: {
flex: 1,
}
}
My modal -- noDevicesModalContainer -- is taking up an enormous amount of the screen and I can't work out why.
I am very new to React Native and web development generally, so please do not be afraid to overexplain!
Thank you in advance for your suggestions.
class DevicesEmptyScreen extends Component {
render() {
return (
<View style={styles.screen}>
<View style={styles.noDevicesImage}>
<Image
source={require('./../../../android/app/src/main/res/drawable/no_devices.png')}
/>
</View>
<View style={styles.noDevicesTextContainer}>
<Text style={styles.noDevicesText}>You do not have any devices yet</Text>
</View>
<View style={styles.noDevicesModalContainer}>
<Text style={[styles.noDevicesText, styles.noDevicesModalText]}>
In case no devices have been assigned, please contact your administrator
</Text>
</View>
</View>
)
}
}
export default DevicesEmptyScreen
const styles = StyleSheet.create({
screen: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
},
noDevicesImage: {
flex: 1,
marginTop: 40
},
noDevicesTextContainer: {
flex: 1,
justifyContent: 'center'
},
noDevicesText: {
color: '#89C7C8',
padding: 10
},
noDevicesModalContainer: {
flex: 1,
backgroundColor: '#EBF5F6',
borderRadius: 10,
marginHorizontal: 30,
marginVertical: 30
},
noDevicesModalText: {
marginLeft: 20
}
})
As per Modal documentation. Try this
<Modal transparent={true}
visible={this.state.isVisible}
onRequestClose={this.closeModal}>
<View style={{
flex: 1,
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center'}}>
<View style={{
width: 300,
height: 300}}>
...
</View>
</View>
</Modal>
I have a flatlist that renders a clickable item (with touchable opacity) and an image background with some text in the middle.
The goal is to render a flatlist that looks like this:
I am trying to add light opacity to the image by adding a view with an overlay and I tried multiple solutions but nothing seems to work.
This is what I have achieved so far:
This is the item in the flatlist:
// console.log("item", item.latest_image.media[0].url);
if (item.empty === true) {
return <View style={[styles.item, styles.itemInvisible]} />;
}
return (
<TouchableOpacity
onPress={() =>
this.props.navigation.push(Screens.Photos, {
team: item,
id: this.props.navigation.getParam("team").id
})
}
>
<ImageBackground
style={styles.backgroundImage}
imageStyle={{ borderRadius: theme.borders_MediumRadius.borderRadius, backgroundColor: 'rgba(255,0,0,.6)' }}
source={{ uri: item.latest_image.media[0].url }}
>
<Text style={styles.itemText}>{item.title.toUpperCase()}</Text>
</ImageBackground>
</TouchableOpacity>
);
};
This is the flatlist:
<SafeAreaView style={{ flex: 1 }}>
<ScrollView
style={{ flex: 1, backgroundColor: "black" }}
scrollEnabled={scrollEnabled}
onContentSizeChange={this.onContentSizeChange}
>
<FlatList
data={formatData(this.state.data, numColumns)}
style={styles.container}
renderItem={this.renderItem}
numColumns={numColumns}
scrollEnabled={scrollEnabled}
/>
<FollowUs />
</ScrollView>
</SafeAreaView>
);
and these are the style props:
container: {
margin: 7.5,
backgroundColor: "black"
},
backgroundImage: {
flex: 1,
height: hp("25"),
backgroundColor: "black",
margin: 7.5,
justifyContent: "center",
alignItems: "center"
},
itemInvisible: {
backgroundColor: "transparent"
},
itemText: {
fontFamily: "RobotoCondensed-Bold",
fontSize: RF(4),
color: "black"
},
overlay: {
backgroundColor: "rgba(255,0,0,0.5)",
alignItems: "center",
justifyContent: "center",
flex: 1,
margin: 7.5,
height: hp("25"), // approximate a square
borderRadius: theme.borders_MediumRadius.borderRadius
}
});
If anybody could help me it would be really appreciated!
Thanks
Here's an example of how you can achieve this
export default class App extends React.Component {
render() {
return (
<View style={styles.container}>
<TouchableOpacity
style={{
backgroundColor: '#FFF',
height: 200,
width: 200,
position: 'relative'
}}>
<ImageBackground
source={{ uri: 'https://placehold.it/200x200' }}
style={{
height: 200,
width: 200,
opacity: 0.6,
position: 'absolute',
}}
/>
<View
style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Hello World!</Text>
</View>
</TouchableOpacity>
</View>
);
}
}
Here's an example Snack - https://snack.expo.io/#hannigan/lonely-bubblegum
You should also set the activeOpacity on the TouchableOpacity to be the same value as what you will set on the ImageBackground (0.6)
Solved it by adding a view around the text and giving it these props:
<View
style={{
flex: 1,
alignItems: "center",
justifyContent: "center",
backgroundColor: "rgba(255,255,255,0.75)",
borderRadius: theme.borders_MediumRadius.borderRadius
}}
>
<Text style={styles.itemText}>{item.title.toUpperCase()}</Text>
</View>
Im trying to make a flatlist with some data and a button on each row.
I have tried to do it in a typical "web" fashion, with nested views and formating the elements relative to their parent, but with no success.
this is the current structure of the list:
<View style={styles.row}>
<View style={styles.rowinfo}>
<View>
<Text style={styles.primaryID}>{item.name ? item.name : item.phoneNumber}</Text>
<Text style={styles.secondaryID}>{item.name ? item.phoneNumber : 'Ukjent innringer'}</Text>
</View>
<View>
<Text style={styles.textalignRight}>Varighet: {item.durationDisplay}</Text>
<Text style={styles.textalignRight}>{item.dateStringTime}</Text>
</View>
</View>
<TouchableOpacity style={styles.rowicon}>
<View style={styles.ban_icon}>
<Icon
name='ban'
type='font-awesome'
color='#FFF'
/>
</View>
</TouchableOpacity>
</View>
And here is my styling:
const styles = StyleSheet.create({
row: {
flex: 1,
marginTop: 1,
paddingVertical: 10,
paddingHorizontal: 15,
flexDirection: "row",
justifyContent: "space-between",
borderBottomWidth: 1,
borderBottomColor: '#f9f9f9'
},
rowinfo:{
flexDirection: "row",
alignSelf: 'stretch'
},
primaryID: {
fontWeight: 'bold'
},
textalignRight: {
textAlign: 'right'
},
rowbt: {
justifyContent: "center",
alignItems: "center",
backgroundColor: 'red'
},
ban_icon: {
color: '#FFF',
fontWeight: 'bold',
fontSize: 14,
marginHorizontal: 8
}
});
I im trying to make it look like this:
But i keep getting this:
import * as React from 'react';
import { Text, View, StyleSheet, TouchableOpacity } from 'react-native';
import Constants from 'expo-constants';
export default class App extends React.Component {
render() {
return (
<View style={styles.container}>
<View style={styles.row}>
<View style={styles.rowinfo}>
<View>
<Text style={styles.primaryID}>{'Phone Number'}</Text>
<Text style={styles.secondaryID}>{'Ukjent innringer'}</Text>
</View>
</View>
<View style={{ flexDirection: 'row'}}>
<View>
<Text style={styles.textalignRight}>Varighet: {'1m og 20s'}</Text>
<Text style={styles.textalignRight}>{'13:23:11'}</Text>
</View>
<TouchableOpacity style={styles.ban_icon}>
<View style={styles.ban_icon} />
</TouchableOpacity>
</View>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: Constants.statusBarHeight,
},
row: {
backgroundColor: 'green',
width: '100%',
marginTop: 1,
paddingVertical: 10,
paddingHorizontal: 15,
flexDirection: "row",
justifyContent: "space-between",
borderBottomWidth: 1,
borderBottomColor: '#f9f9f9'
},
rowinfo:{
flex: 1,
flexDirection: "row",
},
primaryID: {
fontWeight: 'bold'
},
textalignRight: {
textAlign: 'right'
},
ban_icon: {
padding: 10,
backgroundColor: 'red',
marginLeft: 10,
}
});
Check the snack: https://snack.expo.io/#legowtham/43c687
I was able to get my desired result by using absolute positioning.
I need to align two Text component with different fontSize in a row and vertically centered. I have following now https://snack.expo.io/#troublediehard/dmVuZ2
export default class App extends React.Component {
render() {
return (
<View style={styles.container}>
<View style={styles.row}>
<Text style={styles.text1}>Font size 20</Text>
<Text style={styles.text2}>Font size 14</Text>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
row: {
flexDirection: 'row',
backgroundColor: 'red',
},
text1: {
fontSize: 20,
backgroundColor: 'blue',
},
text2: {
fontSize: 14,
backgroundColor: 'green',
},
});
For anyone that didn't found a solution yet, you have to wrap the text within another Text tag:
<View style={styles.container}>
<View style={styles.row}>
<Text>
<Text style={styles.text1}>Font size 20</Text>
<Text style={styles.text2}>Font size 14</Text>
</Text>
</View>
</View>
You need to add alignItems: 'center' to styles.row
row: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: 'red',
},