Flexbox: How to make children the same width as the parent? - css

In my React Native app, I'm having trouble with making the children the same width as the parent. Please see image below:
I want the black and the green View to take the whole screen width, therefore get rid of the white background caused by the parent.
How can I achieve this? For example, I tried to apply width: 100% to the children, doesn't work. Several solutions like this, this and this don't work here.
Here is the code:
<View style={styles.containerWholePage}>
<View>
<View style={styles.upper}></View>
<View style={styles.lower}></View>
</View>
</View>
const styles = StyleSheet.create({
containerWholePage: {
alignItems: 'center',
},
lower: {
alignItems: 'center',
alignSelf: 'stretch',
backgroundColor: 'green',
flex: 6,
width: '100%', // doesn't work
},
upper: {
alignItems: 'center',
alignSelf: 'stretch',
backgroundColor: 'black',
flex: 3,
width: '100%', // doesn't work
},
});
Do you have an idea what I'm doing wrong?

This work for me as you want.
<View style={styles.containerWholePage}>
{/* <View> */}
<View style={styles.upper}></View>
<View style={styles.lower}></View>
{/* </View> */}
</View>
const styles = StyleSheet.create({
containerWholePage: {
alignItems: 'center',
flex:1,
},
lower: {
alignItems: 'center',
alignSelf: 'stretch',
backgroundColor: 'green',
// height:100,
flex: 6,
width: '100%', // doesn't work
},
upper: {
alignItems: 'center',
alignSelf: 'stretch',
backgroundColor: 'black',
flex: 3,
//height:200,
width: '100%', // doesn't work
},
});

Related

React Native: borderBottom does not show up in empty View

In my React Native app, I try to create a simple divider line. As stated here for example, I created an empty View and added the corresponding styling to it.
Now here's the thing: the divider line is not showing up with this code:
<View style={styles.divider}>
<Text></Text>
</View>
... Stylesheet:
divider: {
borderBottomWidth: 1,
borderLeftColor: 'white',
},
But If I add some text lines, it shows up:
<View style={styles.divider}>
<Text>testtest</Text>
</View>
... Stylesheet:
divider: {
borderBottomWidth: 1,
borderLeftColor: 'white',
},
Now here is the code context.
<View style={styles.containerWholePage}>
<View style={styles.containerUpper}>
<Text style={styles.mainText}>Here is a sample text</Text>
</View>
<View style={styles.containerLower}>
<View style={styles.containerText}>
<Text>TEST</Text>
<Text>Example 3</Text>
<Text>18:00 - 20:00</Text>
</View>
<View style={styles.divider}>
<Text>testtest</Text>
</View>
<View style={styles.containerText}>
<Text>TEST2</Text>
<Text>Example 3b</Text>
<Text>18:00 - 19:00</Text>
</View>
</View>
</View>
...
const styles = StyleSheet.create({
containerWholePage: {
alignItems: 'center',
flex: 1,
},
divider: {
borderBottomWidth: 1,
borderBottomColor: 'white',
},
containerLower: {
alignItems: 'center',
alignSelf: 'stretch',
backgroundColor: '#1E2928',
flex: 6,
justifyContent: 'space-around',
},
containerText: {
alignItems: 'center',
backgroundColor: '#1E2928',
},
containerUpper: {
alignItems: 'center',
alignSelf: 'stretch',
backgroundColor: 'white',
flex: 3,
},
});
Maybe you have an idea how to make the bottom line appear without having to write text?
Just do like this:
<View style={styles.divider}/>
...
divider: {
borderBottomWidth: 1,
borderBottomColor: 'white',
width:"100%"
},
Because the width is flexible to it's content, so if nothing in it, it doesn't have width. So that if you set the width, the View will have width setting as you want.
Code sandbox
Basically that should work I just tested it in sandbox and adding a
<View style={{borderBottomWidth: 1}} >
<Text></Text>
</View>
worked perfect for me.. maybe add a {" "} between the Text tags.
you can also try:
<View style={styles.divider}/>
divider: {
borderBottomWidth: 1,
borderBottomColor: 'white',
alignSelf:"stretch"
},
but I prefer just using width: "100%"

React Native vertical text alignment when using explicit height

I want to vertically center my text inside a view with an explicit height.
Center text vertically in react-native did not fully answer my question because they don't use explicit height.
When I use
<View style={styles.rightContainer}>
<Text style={styles.label2}>
Centered
</Text>
</View>
rightContainer: {
marginRight: 10,
flex: 1,
flexDirection: 'row',
justifyContent: 'flex-end',
alignItems: 'center',
},
label2: {
height: 40,
backgroundColor: 'green',
textAlignVertical: 'center',
},
If I take away the explicit height,
label2: {
backgroundColor: 'green',
textAlignVertical: 'center',
},
it works.
I need to set the explicit height because I will convert this View to a tappable button.
How do I make this work?
What am I misunderstanding about react-native layout?
It's because the 'textAlignVertical' property is Android-only. Check the documentation on Text.
You could add an extra container wrapping the text:
export default class FlexDirectionBasics extends Component {
render() {
return (
<View style={styles.rightContainer}>
<View style={styles.labelContainer}>
<Text style={styles.label}>Centered</Text>
</View>
</View>
);
}
}
const styles = {
rightContainer: {
marginRight: 10,
flex: 1,
flexDirection: 'row',
justifyContent: 'flex-end',
alignItems: 'center',
},
labelContainer: {
height: 40,
backgroundColor: 'green',
alignItems: 'center',
justifyContent: 'center',
},
label2: {},
};

How to get rounded image tag on top of two div in react native?

I want to create a profile page where rounded image will be on top of two div in 30:70 ratio where top div will be empty and bottom div will contain few items. I have tried few code snippets from web.
<View style={{ flex: 1, flexDirection: 'column', backgroundColor: 'green', justifyContent: 'flex-start', alignItems: 'flex-start' }}>
<View style={{ flexDirection: 'column', justifyContent: "flex-start", alignItems: "flex-start", alignSelf: "flex-start" }}>
{/* <View style={{ flex: 1, flexDirection: 'row', alignItems: 'flex-end', alignSelf: 'flex-start', margin: 1 }}> */}
<View style={{ backgroundColor: 'white', borderRadius: 10, flexDirection: 'column', height: "30%", width: "100%" }}></View>
{/* </View> */}
<View style={{ flex: 1, flexDirection: 'row', alignItems: 'flex-start', alignSelf: 'flex-start', margin: 1 }}>
<View style={{ backgroundColor: 'white', borderRadius: 10, flexDirection: 'column', height: "70%", width: "100%" }}></View>
</View>
</View>
<View style={{ justifyContent: 'center', alignItems: 'center', alignSelf: 'center', position: 'absolute' }}>
<View style={{
backgroundColor: 'blue',
borderRadius: 10, height: 100, width: 100, borderRadius: 100 / 2
}}></View>
</View>
</View>
reference image
Taking as reference the image you share with us... You can have two views and set the profile avatar style to:
{
position: 'absolute',
alignSelf: 'center',
etc..
}
Check a quick demo: https://snack.expo.io/#abranhe/avatar-example
App.js
import React, { Component } from 'react';
import { Text, View, StyleSheet, ImageBackground, Image } from 'react-native';
import { Ionicons, FontAwesome } from '#expo/vector-icons';
import Constants from 'expo-constants';
import { avatar, background } from './data';
export default class App extends Component {
renderRow({ action, icon, fontAwesome = false }) {
return (
<View style={styles.actionRow}>
{fontAwesome
? <FontAwesome name={icon} size={25} />
: <Ionicons name={icon} size={32} />}
<Text style={styles.text}>{action}</Text>
</View>
);
}
render() {
return (
<View style={styles.container}>
<ImageBackground source={background} style={styles.background}>
<Image source={avatar} style={styles.avatar} />
</ImageBackground>
<View style={styles.content}>
{this.renderRow({ action: 'Scanner', icon: 'ios-camera' })}
{this.renderRow({
action: 'Profile',
icon: 'user-circle-o',
fontAwesome: true,
})}
</View>
</View>
);
}
}
You styles:
const styles = StyleSheet.create({
container: {
flex: 1,
},
background: {
width: '100%',
height: 130,
},
content: {
flex: 1,
marginTop: 80,
marginHorizontal: 10,
},
avatar: {
width: 100,
height: 100,
borderRadius: '50%',
borderWidth: 0.7,
borderColor: 'black',
position: 'absolute',
alignSelf: 'center',
marginTop: 80,
},
actionRow: {
width: '100%',
height: '50',
flexDirection: 'row',
alignItems: 'center',
margin: 10,
},
text: {
marginLeft: 15,
fontWeight: '500',
},
});

Grid like Flatlist component with header looking the same as rows

In react-native I am using FlatList component for rendering a grid-like list of data that looks like:
However, I want to make the first row (or header) with bold text stylesheet. Do I need to renderHeader as another FlatList or is there any better solution for this?
My code for this table:
<View style={stylesCustom.container}>
<FlatList
data={ data }
renderItem={({item}) =><View style={stylesCustom.GridViewBlockStyle}>
<Text style={styles.description} > {item.key} </Text></View>}
numColumns={5}
/>
</View>
const stylesCustom = StyleSheet.create({
container: {
justifyContent: 'center',
flex:1,
marginTop: 20
},
GridViewBlockStyle: {
justifyContent: 'center',
flex: 1,
alignItems: 'center',
backgroundColor: '#00BCD4',
borderWidth: 1,
borderColor: 'black'
},
GridViewInsideTextItemStyle: {
color: '#fff',
padding: 10,
fontSize: 18,
justifyContent: 'center',
},
}

How to align 2 react native elements, 1 being in the center and 1 on the beginning

Lets assume that we have those react native styles:
var styles = StyleSheet.create({
parentView:{
width: 400,
height:150
},
containerView:{
flex:1,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
backgroundColor:'black'
},
child1:{
backgroundColor: 'red',
alignSelf: 'flex-start'
},
child2: {
backgroundColor: 'yellow'
}
}
and that we have this render function:
render: function(){
return(
<View style={styles.parentView}>
<View style={styles.containerView}>
<Text style={styles.child1}>Child1</Text>
<Text style={styles.child2}>Child2</Text>
</View>
</View>
);
}
This code produces this image:
but what I want to achieve is this image:
VERY VERY IMPORTANT: I want child2 to be TOTALLY centered within the containerView, and not a bit far to the right because of the space that child1 occupies.
How can I achieve that in react-native?*
p.s.: Keep in mind that this will run on many resolutions (many screens with different aspect ratios) thus, it cannot be set in an absolute way that would result on it only working on "some" screens but not on others.
not sure if this is the best way to do it, but it works for me
render() {
return(
<View style={styles.parentView}>
<View style={styles.containerView}>
<View style={styles.rowContainer}>
<View style={styles.rowItem}>
<Text style={styles.child1}>Child1</Text>
</View>
<View style={styles.rowItem}>
<Text style={styles.child2}>Child2</Text>
</View>
</View>
</View>
</View>
);
const styles = StyleSheet.create({
parentView:{
width: 400,
height:150
},
containerView:{
flex:1,
flexDirection: 'row',
alignItems: 'center',
backgroundColor:'black'
},
rowContainer: {
flex: 1,
flexDirection: 'column',
},
rowItem:{
flex: 1
},
child1:{
backgroundColor: 'red',
position: 'absolute',
},
child2: {
alignSelf: 'center',
backgroundColor: 'yellow'
}
});

Resources