ReactNative: How to make background image fill up the portion that it should cover by flexbox - react-native

I've been trying to get an image to fill up the space it should fill with flex. However, it only fills up to a certain portion of the space. The structure is as follows:
mainWrapper
navBarWrapper
image
buttonWrapper
mainWrapper is a View with flex: 1 so it covers the entire page.
navBarWrapper has a flex: 1
image has a flex: 7 and backgroundColor: 'pink' to see where it ends
buttonWrapper has a flex: 2.5 and backgroundColor: 'lightgrey' to see where it ends
In the screenshot, the image itself doesn't fill up the pink space entirely.
Screenshot
My simplified code is here:
<View style={styles.mainWrapper}>
<View style={styles.navBarWrapper}>
<NavigationBar
statusBar={this.statusBarConfig()}
leftButton={this.leftButtonConfig()}
title={this.titleConfig()}
style={styles.navBar}>
</NavigationBar>
</View>
<View style={styles.imageWrapper}>
<Image source={require('../assets/images/user_screen/user_screen_background.png')} style={styles.image}>
</Image>
</View>
<View style={styles.buttonWrapper}>
</View>
</View>
And the stylesheet
mainWrapper:{
flex: 1,
flexDirection: 'column',
justifyContent: 'flex-start',
backgroundColor: 'white'
},
navBarWrapper:{
flex: 1,
},
navBar:{
flexDirection: 'row',
alignItems: 'center',
backgroundColor: "#1ca99e",
},
imageWrapper:{
flex: 7,
flexDirection: 'column',
backgroundColor: 'pink',
},
image:{
flex:1 ,
height: null,
width: null,
resizeMode: 'cover'
},
buttonWrapper:{
flex: 2.5,
flexDirection: 'row',
backgroundColor: 'lightgrey'
}

Give subcontainers flex values with respect to wrapping container. Since by default flexDirection is column when you give flex 1 outer container it will take up full height of the screen.
Assuming you need top 10% for navbar, bottom button container 25% of screen height, that gives us 65% of height for the imageWrapper.
mainWrapper:{
flex: 1,
flexDirection: 'column',
justifyContent: 'flex-start',
backgroundColor: 'white'
},
navBarWrapper:{
flex: 0.1,
},
navBar:{
flexDirection: 'row',
alignItems: 'center',
backgroundColor: "#1ca99e",
},
imageWrapper:{
flex: 0.65,
flexDirection: 'column',
backgroundColor: 'pink',
},
image:{
flex:1 ,
height: null,
width: null,
resizeMode: 'cover'
},
buttonWrapper:{
flex: 0.25,
flexDirection: 'row',
backgroundColor: 'lightgrey'
}

Related

Top align elements from the bottom view

I have two Views under my main View
<View style={styles.container}>
<View style={styles.header}>
<Image
resizeMode="contain"
source={require("../assets/logo-large.png")}
style={styles.logo}
/>
</View>
<View style={styles.content}>
<TextInput
style={styles.input}
onChangeText={(email) => setEmail(email)}
defaultValue={email}
placeholder="Your email"
autoCompleteType="email"
textContentType="emailAddress"
></TextInput>
</View>
My code for styling looks like this:
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
},
header: {
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "gold",
},
content: {
flex: 2,
justifyContent: "center",
alignItems: "center",
backgroundColor: "lightblue",
},
});
What I want to achieve is to have a header with logo at the top of the screen and to have the content below, but I want to have all elements in content to be top aligned. At the moment those elements are center aligned in content.
Can someone help with this?
Since your main view defaults to flex-direction = column then your content style justifyContent: "center", will arrange elements from content at vertical middle and alignItems: "center" will make them horizontal center. You need to remove those to keep the content elements to start from the top.
Please update your styles to the following.
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
},
header: {
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "gold",
},
content: {
flex: 2,
alignItems: "center",
backgroundColor: "lightblue",
},
});
Good Luck
I have adjusted it using justifyContent on header and footer styles.
header: {
flex: 1,
justifyContent: "flex-end",
alignItems: "center",
backgroundColor: "gold",
paddingBottom: "10%",
},
content: {
flex: 2,
justifyContent: "flex-start",
alignItems: "center",
backgroundColor: "lightblue",
},

React Native: Vertically and Horizontally align image and text in same row

<View>
<Text>Hello</Text>
<Image source={require('./Vector.png')} />
</View>
I have the above View. I want to vertically and horizontally align image and text. Image should be on the right and text left in the same row. But I am not able to do align them correctly.
You can check here live dmeo here expo-snack:
Also the code is pretty ismple :
import * as React from 'react';
import { Text, View, StyleSheet,Image } from 'react-native';
export default class App extends React.Component {
render() {
return (
<View style={styles.container}>
<Text>Hey</Text>
<Image source={{uri:'https://source.unsplash.com/random'}} style={{height:50,width:50}}/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'space-between',
backgroundColor: '#ecf0f1',
padding: 8,
flexDirection:'row',
alignItems:'center'
}
});
hope it helps. feel free for doubts , and if you want the text and image to be not so distant you can have justifyContent: 'center',
For horizontal:
flexDirection: 'row',
For vertical:
flexDirection: 'column',
Use flexDirection: 'row' to make it in the same row & use justifyContent: 'center', alignItems: 'center' to align it vertically & horizontally.
<View style={{ flex: 1, flexDirection: 'row', justifyContent: 'center', alignItems: 'center' }}>
<Text>Hello</Text>
<Image style={{ width: 50, height: 50 }} source={require('./Vector.png')} />
</View>
You can simply do it by using flexDirection
Example :
<View
style={{
flex: 1,
flexDirection: "row",
alignItems: "center",
justifyContent: "center",
}}
>
<Text>Hello</Text>
<Image
style={{ width: 30, height: 30, resizeMode: "contain" }}
source={require("./Vector.png")}
/>
</View>
If you want to make the image right corner on the screen and text on the left corner try this. It can be done using position
<View
style={{
flex: 1,
flexDirection: "row"
}}
>
<Text style={{ position: "absolute", right: 0 }}>Hello</Text>
<Image
style={{
width: 30,
height: 30,
resizeMode: "contain",
position: "absolute",
left: 0
}}
source={require("./Vector.png")}
/>
</View>

Elevation style prop causing issues with child components

Have all my styling done for two buttons I am using inside header title to switch back between screens. The iOS implementation works perfect but the elevation style prop for Android is causing some issues. It seems to also pass down the elevation style to the child component which in my case is a TouchableOpacity which makes the button click look a little off. Is there any way to fix this issue? See images for a better idea on click impact...
I have attempted to style the TouchableOpacity to elevation:0 to override the issue with no luck. Just to get the elevation style prop to work I had to set a borderColor: 'transparent'.
static navigationOptions = (navData) => {
return {
headerTitle: (
<View style={styles.titleContainer}>
<TouchableOpacity style={styles.mapTitleButton} onPress={() => { navData.navigation.navigate('Map')}}>
<Text style={[styles.titleFont, style={color: Colors.buttonSelected}]}>MAP</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.listTitleButton}>
<Text style={styles.titleFont}>LIST</Text>
</TouchableOpacity>
</View>
),
headerLeft: (
<View style={styles.headerButtonLeft}>
<HeaderButtons HeaderButtonComponent={CustomHeaderButton}>
<Item title="menu" iconName="ios-menu" onPress={() => {
navData.navigation.toggleDrawer()
}} />
</HeaderButtons>
</View>
),
headerRight: (
<View style={styles.placeholder}></View>
),
}
}
}
const styles = StyleSheet.create({
titleContainer: {
alignItems: 'center',
flexDirection: 'row',
height: '60%',
width: '50%',
justifyContent: 'center',
shadowOffset: { width: 0, height: 0 },
shadowOpacity: 0.7,
shadowRadius: 1,
shadowColor: '#000000',
elevation: 5,
borderColor: 'transparent'
},
mapTitleButton: {
backgroundColor: Colors.buttonUnSelected,
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
listTitleButton: {
backgroundColor: Colors.buttonSelected,
flex:1,
alignItems: 'center',
justifyContent: 'center'
},
titleFont: {
fontFamily: 'sailec',
alignItems: 'center',
justifyContent: 'center',
textAlign: 'center',
padding: 10,
fontSize: 13
},
container: {
alignItems: 'center',
justifyContent: 'center',
flex: 1
}
});
Android Screen Capture
Did you try with: TouchableWithoutFeedback
Rather than putting elevation in the parent container I fixed it by putting it in the styling for the actual TouchableOpacity. Good to also note that for Android I needed to set borderColor: 'transparent' to also get the elevation to render.
So styling as shown below:
titleContainer: {
alignItems: 'center',
flexDirection: 'row',
height: '60%',
width: '50%',
justifyContent: 'center',
shadowOffset: { width: 0, height: 0 },
shadowOpacity: 0.7,
shadowRadius: 1,
shadowColor: '#000000',
},
mapTitleButton: {
backgroundColor: Colors.buttonUnSelected,
flex: 1,
alignItems: 'center',
justifyContent: 'center',
elevation: 5,
borderColor: 'transparent'
},
listTitleButton: {
backgroundColor: Colors.buttonSelected,
flex:1,
alignItems: 'center',
justifyContent: 'center',
elevation: 5,
borderColor: 'transparent'
},

Vertical centering in React Native doesn't work

I use a ScrollView and I am not able to center an icon in one of inner Views.
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
<ScrollView>
...
<View style={styles.detailRowContainer}>
<View style={{flex: 1}}>
<Text style={styles.label} numberOfLines={1}>
{'Phone Number'}
</Text>
<Text style={styles.value} numberOfLines={1}>
{phone}
</Text>
</View>
<View style={styles.round}>
<TouchableWithoutFeedback onPress={this._onPressPhone}>
<Icon size={22} name="phone" />
</TouchableWithoutFeedback>
</View>
</View>;
...
</ScrollView>
detailRowContainer: {
flexDirection: 'row',
justifyContent: 'center',
flex: 1,
marginTop: 10,
paddingBottom: 10,
borderBottomWidth: 1,
borderBottomColor: Colors.lightGray,
},
label: {
color: Colors.glofoxDark,
marginBottom: 3,
},
value: {
color: Colors.glofoxDark,
fontWeight: '800',
borderBottomWidth: 1,
borderBottomColor: Colors.lightGray,
},
round: {
backgroundColor: Colors.lightBlue,
width: 30,
height: 30,
borderRadius: 30,
overflow: 'hidden',
justifyContent: 'center',
alignItems: 'flex-end',
flexDirection: 'row',
padding: 4,
},
The styles need to be modified in this way.
Right now you're doing
flexDirection: row along justifyContent: center. Since your first child element is taking complete parent flex, therefore it does not show its effect
paddingBottom is given but , for centering an equivalent paddingTop must be given
padding for the round style should be replaced with margin, otherwise it affects the position of the inner elements
alignItems in round , must not be flex-end, it should be replaced with center
Here are the styles that will fix the vertical centering
detailRowContainer: {
flexDirection: 'row',
alignItems: 'center',
flex: 1,
marginTop: 10,
paddingTop: 10,
paddingBottom: 10,
borderBottomWidth: 1,
borderBottomColor: Colors.lightGray,
},
round: {
backgroundColor: Colors.lightBlue,
width: 30,
height: 30,
borderRadius: 30,
overflow: 'hidden',
justifyContent: 'center',
alignItems: 'center',
margin: 4
},

Flexbox height in React Native

I'm trying to create a simple content-sized dialog box in React Native. Highest in this hierarchy I have my overlay <View> styled so:
{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
zIndex: 100,
backgroundColor: COLOR
}
Within this, I have a wrapper <View> with this style:
{
flex: 1,
alignItems: 'center',
justifyContent: 'center'
}
Then I have the dialog <View>:
{
flex: 1,
width: '86%',
maxWidth: 450,
flexDirection: 'column',
justifyContent: 'flex-start',
alignItems: 'flex-start',
backgroundColor: 'white',
borderWidth: 5,
borderColor: 'gold'
}
It looks like the problem, though, lies in the way I'm building the dialog:
<View style={{flex: 1, flexDirection: 'row', justifyContent: 'flex-start', alignItems: 'flex-start'}}>
<Image source={require('../../assets/icons/warning.png')}
style={{resizeMode: 'contain', height: 50, width: 48, marginRight: 30}} />
<View style={[flex: 1, flexDirection: 'column', justifyContent: 'flex-start', alignItems: 'flex-start']}>
<Text>{this.props.dialogMessage}</Text>
<View style={{flex: 1, width: '100%', flexDirection: 'row', justifyContent: 'space-between', alignItems: 'flex-start'}}>
<Button dismissOverlay={this.props.dismissOverlay} />
</View>
</View>
</View>
With this styling I get this result:
If I change flex to 0, I get this instead:
How can I get the dialog to size to the content?
In your Dialog <View> don't set flex at all. Have it like this
{
width: '86%',
maxWidth: 450,
flexDirection: 'column',
justifyContent: 'flex-start',
alignItems: 'flex-start',
backgroundColor: 'white',
borderWidth: 5,
borderColor: 'gold'
}
If it does not work, could you provide more code on the content inside of your Dialog view?