This question already has answers here:
CSS Grid - 2x2 grid always taking up the full width when possible
(1 answer)
How to set up a dynamic grid based on flex or grid
(1 answer)
Closed yesterday.
I want to create a dynamic grid in the flatlist, but it is not dynamic when data increases, my data is an array of object which has images and other information too.
I am using
columnWrapperStyle={{flexWrap: 'wrap', flex: 1 / 2}}
width: "100%",
height: height / 2.3,
I want to create something like this
if there is one image the grid should cover full width and if two images it should take half of width,
now the main issue I want to do something when there are three images the first height should be full and others will divide the height in half, same for the last one.
thanks.
You should use or get inspired by this package - https://www.npmjs.com/package/react-native-fb-image-grid
import React, { Component } from "react";
import { StyleSheet, View } from "react-native";
import FbGrid from "react-native-fb-image-grid";
class App extends Component {
render() {
return (
<View style={styles.container}>
<View style={styles.inner_container}>
<FbGrid
images={[
"https://facebook.github.io/react-native/docs/assets/favicon.png",
]}
/>
</View>
<View style={styles.inner_container}>
<FbGrid
images={[
"https://facebook.github.io/react-native/docs/assets/favicon.png",
"https://facebook.github.io/react-native/docs/assets/favicon.png",
]}
/>
</View>
<View style={styles.inner_container}>
<FbGrid
images={[
"https://facebook.github.io/react-native/docs/assets/favicon.png",
"https://facebook.github.io/react-native/docs/assets/favicon.png",
"https://facebook.github.io/react-native/docs/assets/favicon.png",
]}
/>
</View>
<View style={styles.inner_container}>
<FbGrid
images={[
"https://facebook.github.io/react-native/docs/assets/favicon.png",
"https://facebook.github.io/react-native/docs/assets/favicon.png",
"https://facebook.github.io/react-native/docs/assets/favicon.png",
"https://facebook.github.io/react-native/docs/assets/favicon.png",
"https://facebook.github.io/react-native/docs/assets/favicon.png",
"https://facebook.github.io/react-native/docs/assets/favicon.png",
]}
/>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: "center",
justifyContent: "center",
backgroundColor: "#eee",
},
inner_container: {
width: "100%",
height: "20%",
},
});
export default App;
Live Demo - https://snack.expo.dev/#emmbyiringiro/c182c6
Related
When attempting to use ScrollView it appears to not respect justifyContent of its parent container.
import React from 'react';
import { Text, ScrollView, StyleSheet, TextStyle, View, ViewStyle } from 'react-native';
interface TODO_TextCard {
text: string,
}
export const TODO_TextCard: React.FunctionComponent<TODO_TextCard> = (props: TODO_TextCard) => {
return <View style={styles.viewStyle}>
<ScrollView>
<Text style={styles.quoteTextStyle}>{props.text}</Text>
</ScrollView>
</View>;
}
const styles = StyleSheet.create({
quoteTextStyle: {
fontSize: 30,
fontStyle: 'italic'
} as TextStyle,
viewStyle: {
flex: 1,
borderWidth: 2, borderColor: 'red',
justifyContent: 'center',
paddingHorizontal: 10
} as ViewStyle,
});
<TODO_TextCard text={'The mind adapts and converts to its own purposes the obstacle to our acting. The impediment to action advances action. What stands in the way becomes the way'}/>
Rendered as:
Now if I remove the and just render text such as
export const TODO_TextCard: React.FunctionComponent<TODO_TextCard> = (props: TODO_TextCard) => {
return <View style={styles.viewStyle}>
<Text style={styles.quoteTextStyle}>{props.text}</Text>
</View>;
}
The Text element does respect the justifyContent:center of the parent and renders as:
Is it possible for Scroll view to be centered?
The solution that I have in mind right now is to check the length of the text and conditionally render Scroll View something like:
/** This some text length would have to be different depending on the device screen, and
* even with different device screens would still not work all the time if the text
* can have new lines in it.*/
const SOME_TEXT_LENGTH = 300;
export const TODO_TextCard: React.FunctionComponent<TODO_TextCard> = (props: TODO_TextCard) => {
return <View style={styles.viewStyle}>
{props.text.length > SOME_TEXT_LENGTH ?
<ScrollView>
<Text style={styles.quoteTextStyle}>{props.text}</Text>
</ScrollView>
:
<Text style={styles.quoteTextStyle}>{props.text}</Text>
}
</View>;
}
Which very much is not ideal, due to different device screens as well as text potentially having new lines.
The ScrollView does in fact respect the justifyContent:center of its parent. The ScrollView is placed in the center of the outer View component. But here the ScrollView takes up the whole vertical screen, so it seems like it is not centered.
Try setting <ScrollView style={{backgroundColor: 'green'}}> to see what i mean.
Try applying viewStyle or a similar styling to the ScrollView itself. Make sure that you use the attribute contentContainerStyle instead of style. This snippet works for me.
<View style={styles.viewStyle}>
<ScrollView contentContainerStyle={{flex: 1, justifyContent: 'center'}}>
<Text style={styles.quoteTextStyle}>{props.text}</Text>
</ScrollView>
</View>
I also found this article. Maybe it will also help you out.
You need to give styling to ScrollView, for styling ScrollView you can use style or contentContainerStyle prop:
style defines the outer container of the ScrollView, e.g its height and relations to siblings elements
contentContainerStyle defines the inner container of it, e.g items alignments, padding, etc
In your case you need to give contentContainerStyle to position your items for eg:
return (
<View style={styles.viewStyle}>
{props.text.length > SOME_TEXT_LENGTH ?
<ScrollView
contentContainerStyle={{
flex: 1, //To take full screen height
justifyContent: 'center',
alignItems: 'center,
}}>
<Text style={styles.quoteTextStyle}>{props.text}</Text>
</ScrollView>
:
<Text style={styles.quoteTextStyle}>{props.text}</Text>
}
</View>
);
I am trying to achieve dynamic padding top and bottom. I am aware that paddingTop and paddingBottom with % will use the width of the container and I am fine with that.
Unfortunately when I do set the paddingTop to any value with %, it sets the paddingBottom to the same value. Basically paddingTop: '5%', paddingBottom: '0%' will give me equal 5% paddings on both sides.
If I set paddingBottom to any % value - it's just being added to the value that came form the top. So: paddingTop: '5%', paddingBottom: '10%' results in paddingBottom equal to 15%...
I checked the same solution in a web project and there it works as expected.
The snack presenting the problem:
https://snack.expo.io/BJ9-2t8LB
The problem is on both Android and iOS.
How to solve it?
Apply the value to the child container to be applied, not to the parent container.
I have modified the answer according to the conditions you want. You should send Bottom's territory to the parent's container. Because they interact with each other in their child's container, they must be independent.
import * as React from 'react';
import { Text, View, StyleSheet } from 'react-native';
export default class App extends React.Component {
render() {
return (
<View style={styles.wrapper}>
<View style={styles.inner}>
<View style={{ backgroundColor: 'yellow' }}>
<Text>TOP</Text>
</View>
</View>
<View style={{ backgroundColor: 'red', }}><Text>BOTTOM</Text></View>
</View>
);
}
}
const styles = StyleSheet.create({
wrapper: {
flex:1,
paddingLeft: 24,
paddingRight: 24,
backgroundColor: 'green',
paddingBottom:"5%"
},
inner: {
flex:1,
justifyContent: 'space-between',
backgroundColor: 'blue',
marginTop:"10%"
},
});
That is strange behavior, you should bring it up as an issue to react-native.
In the meantime, a workaround would be applying marginTop and marginBottom to the inner View, instead of paddingTop and paddingBottom to the wrapper View.
const styles = StyleSheet.create({
ayz:{
marginTop:"15%",
backgroundColor:'pink',
alignItems:'center',
justifyContent:'center',
},
asd:{
color:'white',
fontSize:50,
fontWeight:'bold'
}
});
I'm trying to use percentage value for margin style attribute on my React Native project but it seems to reduce the height of one of my View component. If I replace percentage value by an absolute value, there is no more issue and it works fine. Did you try to use percentage value as margin in React Native ? Here is a little sample of code to reproduce this issue:
import React, { Component } from 'react';
import { Text, View, StyleSheet } from 'react-native';
export default class App extends Component {
render() {
return (
<View style={styles.scene}>
<View style={styles.card}>
<View style={styles.container}>
<Text>Hello World</Text>
</View>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
scene: {
backgroundColor: '#F9E8D5',
flex: 1,
justifyContent: 'flex-start',
alignItems: 'center',
flexDirection: 'column'
},
card: {
backgroundColor: '#E6D5C3',
flex: 0.2,
flexDirection: 'column',
marginTop: '20%' // Replace by 20
},
container: {
backgroundColor: '#FFFFFF',
flex: 1,
flexDirection: 'column',
justifyContent: 'center'
}
});
Thank you very much !
A component's height and width determine its size on the screen.
The simplest way to set the dimensions of a component is by adding a fixed width and height to style. All dimensions in React Native are unitless, and represent density-independent pixels.
Setting dimensions this way is common for components that should always render at exactly the same size, regardless of screen dimensions.
Use flex in a component's style to have the component expand and shrink dynamically based on available space. Normally you will use flex: 1.
The following references will be use for styling
https://facebook.github.io/react-native/docs/height-and-width.html
https://medium.com/the-react-native-log/tips-for-styling-your-react-native-apps-3f61608655eb
https://facebook.github.io/react-native/docs/layout-props.html#paddingtop
Use Dimensions to calculate to get the height and width of the screen.
var {height, width} = Dimensions.get('window');
To specify percentage by getting the screen size and convert it into percentage.
Sample example:
const { height } = Dimensions.get('window');
paddingTop: height * 0.1 // 10 percentage of the screen height
This is a real bug but Facebook does not care.
https://github.com/facebook/react-native/issues/19164
I'm trying to align Views in React Native, and I want that every View is 50% of the screen. Something like :
My state is :
this.state = {
companies: [
{logo_url: require("../../../img/company_logos/ald.png")},
{logo_url: require("../../../img/company_logos/arval.png")},
{logo_url: require("../../../img/company_logos/businesslease.png")},
{logo_url: require("../../../img/company_logos/dieterenusedcars.png")},
{logo_url: require("../../../img/company_logos/psa.png")},
{logo_url: require("../../../img/company_logos/remarketing_center.png")},
{logo_url: require("../../../img/company_logos/vdfin.png")}
]
}
And then in the render method :
render(){
return (
<View style={{flex: 1, flexDirection: 'row'}}>
{this.state.companies.map(company => {
return (
<View style={{width: Dimensions.get('window').width * 0.5, height: 150}}>
<Image source={company.logo_url} style={{width: Dimensions.get('window').width * 0.5, height: 100}}/>
</View>
);
})}
</View>
)
}
But I see only first two logos.
All items are probably shown in one row instead of going to second row if there is no more place on the screen.
Any advice?
In case somebody else has the same problem.
I solved it by adding flexWrap: "wrap" to the parent View
<View style={{flex: 1, flexDirection: 'row', flexWrap: "wrap"}}>
I am trying to align the social icon texts under each image like so:
However, I am getting these results:
I placed each row as a separate view
<View style={styles.socialIcons}>
<Image source={require("social/facebook-icon.png")} />
<Image source={require("social/twitter-icon.png")} />
<Image source={require("social/mail-icon.png")} />
<Image source={require("social/message-icon.png")} />
</View>
<View style={styles.socialIconsText}>
<Text style={styles.socialIconText}>Facebook</Text>
<Text style={styles.socialIconText}>Twitter</Text>
<Text style={styles.socialIconText}>Email</Text>
<Text style={styles.socialIconText}>Message</Text>
</View>
followed by their styles:
socialIcons: {
alignItems: 'center',
flex: 1,
flexDirection: 'row',
justifyContent: 'space-between',
paddingLeft: 40,
paddingRight: 40,
},
socialIconsText: {
backgroundColor: 'transparent',
alignItems: 'center',
flex: 1,
flexDirection: 'row',
justifyContent: 'space-between',
paddingLeft: 40,
paddingRight: 40,
},
I think what I should be doing instead is to place the text inside the image tags but, when I do that the images height cuts off any text under it. Is there a way to get the image heights and increase the height in the styles?
Or is there a better way to align the text underneath the images?
i think the padding interferes with the text.
also try to make every image and text element 25% in width + box-sizing: border-box; and center text.
İnstead of seperating image and text of facebook, twitter ... Covering them in a special wiew is better idea. In this way you will have much more control on your views and you can make a dynamic implementation.
<View style = {{flex:1}}>
<View style={{height:80, width:80}}>
<Image style ={{flex:1}}>
...
</Image>
<Text style={{flex:1}}>
</Text>
</View>
.
.
.
</View>
Creating a function for returning special views will save you from repeating codes.
getSpecView(uri,text)//use this params to specify your images and texts
{
return(
...
);
}
And now you just have to do is calling this function
<View style = {{flex:1}}>
getSpecView(*faceuri, *facetext)
getSpecView(*twitter, *twittertext)
.
.
</View>
You can even get rid of calling this function several times for every couple by creating an Json array and calling map function
couples = [{ name:'facebook', uri:'faceuri' }, { name:'twitter', uri:'twitter uri'}]
and now you just have a three lines of codes + a function and a json array.
<View style = {{flex:1}}>
couples.map(this.getSpecView(name,uri))// not sure about syntax
</View>
If you have trouble with images you can use resizeModes
resizeMode PropTypes.oneOf(['cover', 'contain', 'stretch', 'repeat', 'center'])
https://facebook.github.io/react-native/docs/image.html