Grid layout using flex In React Native - react-native

I am using flex to display some profile.
<View style={styles.flexContainer}>
<View style={styles.profileImgContainer} >
<Image style={styles.profileImg}/>
</View>
<View style={styles.name}>
<Markdown>{user.name}</Markdown>
</View>
</View>
const styles = StyleSheet.create({
flexContainer: {
flexDirection: 'row'
},
...,
});
I want to put Image in center of col1 using row1 and row2.
I want to put Markdown in col2 of row1.
My flex container should look like this.
col1 | col2 |
row1 |______|
| |
row2 ____|______|
How I can do this ?

Output:
Code:
<View style={styles.container}>
<View style={{flex: 1, flexDirection: 'row'}}>
<View style={styles.col1}>
<Image source={{uri: 'https://www.deine-tierwelt.de/magazin/wp-content/uploads/sites/2/2013/10/Australian-Cattle-Dog-1000x570.jpg'}} style={{width: 100, height: 100}} />
</View>
<View style={styles.col2}>
<View style={styles.row1}>
<Text> Username </Text>
</View>
<View style={styles.row2}>
</View>
</View>
</View>
<View style={{flex: 1}} />
</View>
Stylesheet:
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
flexDirection: 'column',
padding: 8,
},
col1: {
flex: 1,
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'gray'
},
col2: {
flex:1,
flexDirection: 'column'
},
row1: {
flex: 1,
flexDirection: 'row',
justifyContent: 'center',
backgroundColor: 'lightgray'
},
row2: {
flex: 1,
flexDirection: 'row',
justifyContent: 'center',
backgroundColor: 'darkgray'
}
Demo:
https://snack.expo.io/eoENHOHvq

Check below code
<View style={{ flex: 1, flexDirection: 'row' }}>
{/* column 1 */}
<View style={{ flex: 1, backgroundColor: 'green', justifyContent: 'center', alignItems: 'center' }}>
<Image
style={{ width: 50, height: 50 }}
source={{
uri: 'https://reactnative.dev/img/tiny_logo.png',
}}
/>
</View>
{/* column 2 */}
<View style={{ flex: 1 }}>
{/* row 1 */}
<View style={{ flex: 1, backgroundColor: 'red', justifyContent: 'center', alignItems: 'center' }}>
<Text>Hello</Text>
</View>
{/* row 2 */}
<View style={{ flex: 1, backgroundColor: 'yellow' }}>
</View>
</View>
</View>
Hope this helps you. Feel free for doubts.

Related

React Native function to render Element dynamically doesn't render anything

I wrote a function to render views dynamically based on an object. But the function does not render any views when invoked.
I've tried adding and taking away render() in my function but it doesn't seem to work.
var arr = this.state.response;
Object.keys(arr).map(key => {
console.log(arr[key]);
return (
<View style={{ flex: 1, alignSelf: 'stretch', flexDirection: 'row' }}>
<View style={{ flex: 1, alignSelf: 'stretch'}}>
<Text>{key}</Text>
</View>
<View style={{ flex: 1, alignSelf: 'stretch'}}>
<Text>{arr[key].sales}</Text>
</View>
<View style={{ flex: 1, alignSelf: 'stretch'}}>
<Text>{arr[key].sales}</Text>
</View>
<View style={{ flex: 1, alignSelf: 'stretch'}}>
<Text>{arr[key].sales}</Text>
</View>
<View style={{ flex: 1, alignSelf: 'stretch'}}>
<Text>{arr[key].sales}</Text>
</View>
</View>
)
})
}
And the renderRow function is called in the view like this
render() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<View style={{ flex: 1, alignSelf: 'stretch', flexDirection: 'row' }}>
<View style={{ flex: 1, alignSelf: 'stretch' }}>
<Text>Name</Text>
</View>
<View style={{ flex: 1, alignSelf: 'stretch' }}>
<Text>Sales</Text>
</View>
<View style={{ flex: 1, alignSelf: 'stretch' }}>
<Text>Commission</Text>
</View>
<View style={{ flex: 1, alignSelf: 'stretch' }}>
<Text>Payout</Text>
</View>
<View style={{ flex: 1, alignSelf: 'stretch' }}>
<Text>Profit</Text>
</View>
</View>
{this.renderRow()}
</View>
);
}
change renderRow function
renderRow = () => {
const arr = this.state.response;
return Object.keys(arr).map(key =>
<View style={{ flex: 1, alignSelf: 'stretch', flexDirection: 'row' }}>
<View style={{ flex: 1, alignSelf: 'stretch'}}>
<Text>{key}</Text>
</View>
<View style={{ flex: 1, alignSelf: 'stretch'}}>
<Text>{arr[key].sales}</Text>
</View>
<View style={{ flex: 1, alignSelf: 'stretch'}}>
<Text>{arr[key].sales}</Text>
</View>
<View style={{ flex: 1, alignSelf: 'stretch'}}>
<Text>{arr[key].sales}</Text>
</View>
<View style={{ flex: 1, alignSelf: 'stretch'}}>
<Text>{arr[key].sales}</Text>
</View>
</View>
}
Your renderRow function does not return anything...
return Object.keys(arr).map(key => {

Why backgroundColor doesn't work with View in React Native?

I'm trying to make a top menu and colorize it, but backgroudColor property doesn't work.
How the app looks now
<View>
<View style={{
flex: 1,
height: 50,
flexDirection: 'row',
justifyContent: 'space-between',
backgroundColor: 'skyblue'
}}>
<View style={{flex: 1, backgroundColor: 'skyblue'}}><Text style={style.upMenu.text}>H</Text></View>
<View style={{flex: 1, backgroundColor: 'skyblue'}}><Text style={style.upMenu.text}>Plugins</Text></View>
<View style={{flex: 1, backgroundColor: 'skyblue'}}><Text style={style.upMenu.text}>Remote</Text></View>
<View style={{flex: 1, backgroundColor: 'skyblue'}}><Text style={style.upMenu.text}>P</Text></View>
</View>
</View>
Solved
Thanks a lot, your answers both are very useful!
Give prop flex:1 to the parent view style.
<View style={{flex:1}}>
.....Child Views
</View>
use the code below,
<View style={{ flex: 1 }}>
<View
style={{
flex: 1,
height: 50,
flexDirection: "row",
justifyContent: "space-between",
backgroundColor: "#87ceeb",
maxHeight: 20
}}
>
<View style={{ flex: 1, backgroundColor: "#87ceeb" }}>
<Text style={style.upMenu.text}>H</Text>
</View>
<View style={{ flex: 1, backgroundColor: "#87ceeb" }}>
<Text style={style.upMenu.text}>Plugins</Text>
</View>
<View style={{ flex: 1, backgroundColor: "#87ceeb" }}>
<Text style={style.upMenu.text}>Remote</Text>
</View>
<View style={{ flex: 1, backgroundColor: "#87ceeb" }}>
<Text style={style.upMenu.text}>P</Text>
</View>
</View>
</View>
to get the required header height use the maxHeight to change it

How to align a View to center without changing children's position?

<View style={{height: '100%', width: '100%'}}>
{OtherContent}
<ScrollView>
<View style={{flexDirection: 'row', flexWrap: 'wrap', padding: 20}}>
{children}
</View>
<ScrollView>
</View>
I want the View inside ScrollView to be in center of the screen without changing it's children position
Children:
<View style={Styles.docsContainer}>
{arr.map((document, index) => {
return (
<TouchableOpacity key={index} style={[Style.docStyle} onPress={null}>
<Icon name='file-text-o'/>
<Text>{document.name}</Text>
</TouchableOpacity>
);
})}
</View>
const Styles: {
docsContainer: {
flexDirection: 'row',
flexWrap: 'wrap',
padding: 20,
},
docStyle: {
alignItems: 'center',
padding: 20,
margin: 5,
marginBottom: 10,
borderRadius: 8,
width: 170
}
}
Indeed, we don't need parent View, we just need scrollView as flewGrow 1 which makes scrollView have full height and width as per device.
My approach:
<ScrollView contentContainerStyle={{ flexGrow: 1, justifyContent: 'center', alignItems: 'center' }}>
<View style={{
alignItems: 'center',
justifyContent: 'center',
flex: 1,
}}>
<Text>mahesh nandam</Text>
</View>
</ScrollView>
Try this.
The Viewis your ScrollView's immediate children. So you can style ScrollView using contentContainerStyle and align it in center like this.
<View style={{height: '100%', width: '100%'}}>
<ScrollView
contentContainerStyle={{
flexGrow: 1,
justifyContent: 'center',
alignItems: 'center',
}}
>
<View style={{flexDirection: 'row', flexWrap: 'wrap', padding: 20}}>
{children}
</View>
<ScrollView>
</View>
I guess it's what you're loooking for.
Center Horizontally
If you only want to center the View horizontally, you can set alignItems: 'center' to ScrollView's contentContainerStyle.
<View style={{ height: '100%', width: '100%' }}>
<Text>Other content</Text>
<ScrollView contentContainerStyle={{ alignItems: 'center' }}>
<View style={{ flexDirection: 'row', flexWrap: 'wrap', padding: 20, backgroundColor: 'red' }}>
<Text>children</Text>
</View>
</ScrollView>
</View>
The inner View is highlighted in red.
Center Horizontally and Vertically
In this case, you can set { flex: 1, justifyContent: 'center', alignItems: 'center' } for the same contentContainerStyle.
<View style={{ height: '100%', width: '100%' }}>
<Text>Other content</Text>
<ScrollView contentContainerStyle={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<View style={{ flexDirection: 'row', flexWrap: 'wrap', padding: 20, backgroundColor: 'red' }}>
<Text>children</Text>
</View>
</ScrollView>
</View>
If what you expect is different layout than in either of the screenshots, please share a simple sketch of the layout.

Setting `backgroundColor` in style hides `View` component

I have the following render() function in my component, it is replicating the look and feel of a table, but using flex in react-native.
<View>
<View key={ 'test' } style={{ flex: 1, flexDirection: 'row' }}>
<View style={{ flex: 1, alignSelf: 'stretch' }}>
<Text>Col1</Text>
</View>
<View style={{ flex: 1, alignSelf: 'stretch' }}>
<Text>Col2</Text>
</View>
<View style={{ flex: 1, alignSelf: 'stretch' }}>
<Text>Col3</Text>
</View>
<View style={{ flex: 1, alignSelf: 'stretch' }}>
<Text>Col4</Text>
</View>
<View style={{ flex: 1, alignSelf: 'stretch' }}>
<Text>Col5</Text>
</View>
</View>
</View>
Which renders perfectly fine and as expected. However if I add backgroundColor: 'green' into the style of the top-most-level view, above, then the whole view is just gone. Can't even see it in the react-native inspector anymore.
Any idea why this is happening? Am I missing some gotcha, to do with not using background colors on nested View or something?
Edit: It is because there was a being wrapped around my component from the parent component, which also had to have flex: 1 explicitly set. Not sure why only adding backgroundColor causes this but there we go.
You have to set the style of the first view to flex: 1
<View style={{flex: 1}}>
<View key={ 'test' } style={{ flex: 1, flexDirection: 'row', backgroundColor: 'green' }}>
<View style={{ flex: 1, alignSelf: 'stretch' }}>
<Text>Col1</Text>
</View>
<View style={{ flex: 1, alignSelf: 'stretch' }}>
<Text>Col2</Text>
</View>
<View style={{ flex: 1, alignSelf: 'stretch' }}>
<Text>Col3</Text>
</View>
<View style={{ flex: 1, alignSelf: 'stretch' }}>
<Text>Col4</Text>
</View>
<View style={{ flex: 1, alignSelf: 'stretch' }}>
<Text>Col5</Text>
</View>
</View>
</View>
You can try this, I think by setting the height and width to your parent view solve the problem
<View key={ 'test' } style={{ height: 500, width:500, flexDirection: 'row' }}>
<View style={{ flex: 1, alignSelf: 'stretch' }}>
<Text>Col1</Text>
</View>
<View style={{ flex: 1, alignSelf: 'stretch' }}>
<Text>Col2</Text>
</View>
<View style={{ flex: 1, alignSelf: 'stretch' }}>
<Text>Col3</Text>
</View>
<View style={{ flex: 1, alignSelf: 'stretch' }}>
<Text>Col4</Text>
</View>
<View style={{ flex: 1, alignSelf: 'stretch' }}>
<Text>Col5</Text>
</View>
</View>

Loading View programatically takes too long

I'm trying to create a table from an array. However, loading it takes a bit too long. Is there a way to speed it up?
allData contains about 250 arrays
Function to generate rows
renderRow = (num,one,three,four,five) => {
return (
<View key={num} style={{ flex: 1, alignSelf: 'stretch', flexDirection: 'row' }}>
<View style={{ flex: 0.5, alignSelf: 'stretch' }}>
<Text style={{ textAlign: 'center' }}>{num}</Text>
</View>
<View style={{ flex: 1, alignSelf: 'stretch' }}>
<Text style={{ textAlign: 'center' }}>{one}</Text>
</View>
<View style={{ flex: 1, alignSelf: 'stretch' }}>
<Text style={{ textAlign: 'center' }}>{three}</Text>
</View>
<View style={{ flex: 1, alignSelf: 'stretch' }}>
<Text style={{ textAlign: 'center' }}>{four}</Text>
</View>
<View style={{ flex: 1, alignSelf: 'stretch' }}>
<Text style={{ textAlign: 'center' }}>{five}</Text>
</View>
</View>
);
}
Displaying the table is what takes about 5 seconds
DrawSchedule = () => {
var allData = this.state.allData;
var Rows = [];
var Table = [];
allData.map((datum) => {
Rows.push(this.renderRow(datum[0],datum[1],datum[3],datum[4],datum[5]));
})
Table = [];
Table.push(
<View key="head" style={styles.tableContainer}>
<View style={{ flex: 1, alignSelf: 'stretch', flexDirection: 'row' }}>
<View style={{ flex: 0.5, alignSelf: 'stretch' }}>
<Text style={{ textAlign: 'center' }}>Title A</Text>
</View>
<View style={{ flex: 1, alignSelf: 'stretch' }}>
<Text style={{ textAlign: 'center' }}>Title B</Text>
</View>
<View style={{ flex: 1, alignSelf: 'stretch' }}>
<Text style={{ textAlign: 'center' }}>Title C</Text>
</View>
<View style={{ flex: 1, alignSelf: 'stretch' }}>
<Text style={{ textAlign: 'center' }}>Title D</Text>
</View>
<View style={{ flex: 1, alignSelf: 'stretch' }}>
<Text style={{ textAlign: 'center' }}>Title E</Text>
</View>
</View>
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
{Rows}
</View>
</View>
)
this.state.Table = Table;
this.setState({Table: this.state.Table});
}
render() {
return (
<View style={styles.container}>
<ScrollView>
<Button
style={styles.loginButton}
onPress={this.DrawSchedule}
title="Load Data"
/>
{this.state.Table}
</ScrollView>
</View>
);
}
Use FlatList to render large list for performance:
import { FlatList } from 'react-native';
render() {
return (
<FlatList
data={this.state.data}
keyExtractor={(item) => ....}
renderItem={({ item }) => (
<View>
...
</View>
)}
/>
);
}
Please read FlatList