I'm hoping to get help building an Image Grid in React Native.
I'm trying to create an image grid with mapped data from an array. The mapping part is working fine but the images are not being place the way I want.
This is what I'm looking for (images placed where red squares are):
This is my code so far:
<ScrollView style={{flex: 1, backgroundColor: 'yellow',
}} >
{data.map(image => (
<View style={styles.viewpic}>
<Image style={styles.image} source={{uri:image.url }}/>
</View>
))}
</ScrollView>
</SafeAreaView>
This is my CSS:
viewpic: {
flex: 1,
flexWrap:'wrap',
justifyContent: 'center',
flexDirection: 'row',
backgroundColor: 'blue',
},
image: {
justifyContent: 'center',
height: 115,
width: 115,
margin:6,
backgroundColor: 'red',
}
This is what I'm currently getting:
So far I tried every single CSS combo I could think but nothing has worked so far.
I also tried FLATLIST but to be honest I wasn't able to properly convert my current code to "fit" the requirements of Flatlists.
Thanks everyone for your help!
Cheers!
it's an HTML mistake.
In fact, you put the flex-wrap style for each element, that's why you have one element per line.
You have to put all the elements inside the flex-wrap div and it will works. I hope it will help you
<View style={styles.viewpic}>
{data.map(image => (
<Image style={styles.image} source={{uri:image.url }}/>
))}
</View>
I was able to find the answer!
I combined 2 tutorials + a few tricks and got it done!
First I built my image grid using "FlatList". I found a great tutorial with the step by step here(not my page, not affiliated):Youtube Tutorial
At the beginning I was getting the same result until I added "numColumns={ }"
Here's the code:
...
const numberOfCols = 3
...
return(
.
<View>
<FlatList
data={data}
keyExtractor={(item, index)=>{return item.date}}
numColumns={numberOfCols}
renderItem={({item, index})=>(
<View style={styles.viewpic}>
<Image style={styles.image} source={{uri:item.url}}/>
</View>
)}
/>
Then I used a bit of the strategy from this tutorial (not my page, not affiliated) :
Youtube Tutorial
I still need to adjust the css so it looks better but I'm happy with it so far.
Here is the final result:
Related
i got an problem with the refreshing on pull function. The FlatList renders fine, but pull to refresh is not working. This is my current sourcecode:
return (
<View style={GlobalStyles.flex1}>
<FlatList
showsVerticalScrollIndicator={false}
refreshControl={
<RefreshControl
refreshing={isRefreshing}
onRefresh={() => {
console.log("onRefresh loadVocable");
loadVocables();
}}
/>
}
data={vocables}
keyExtractor={vocable => vocable.id}
onEndReached={() => {
if (!isRefreshing && !endReached) {
loadVocables();
}
}}
renderItem={vocable => (
<TouchableOpacity
onPress={() => {
props.navigation.navigate({ routeName: "editVocable", params: { vocable: vocable.item } });
}}
onLongPress={() => {
handleLongPress(vocable.item.id);
}}>
<Card style={styles.cardStyle}>
<View style={styles.part1}>
<Text style={styles.vocableText}>{vocable.item.wordENG}</Text>
<Text style={styles.vocableText}>{vocable.item.wordDE}</Text>
</View>
<View style={styles.part2}>
<Ionicons name={vocable.item.known ? "md-checkmark-circle" : "md-close-circle"} size={23} color={vocable.item.known ? Colors.success : Colors.danger} />
</View>
</Card>
</TouchableOpacity>
)}
/>
</View>
);
In the official docs is an example that says contentContainerStyle needs to be flex: 1 to know the height, that makes sence to me, so when i set contentContainerStyle with flex 1, refresh on pull works fine, but then i can't scroll anymore in the Flatlist and everthing get very tight, so the style also change then. Does anyone know why this happen?
The first picture is with "contentContainerStyle={{flex: 1}}" and the last one is without contentContainerStyle.
The answer was so easy, I compared a new project (there worked my code) to the one where the problem was and after 5 days I found the little error:
My import was wrong!
I imported FlatList like this:
import { FlatList } from "react-native-gesture-handler";
But it needs to get imported from React-Native so like this:
import { FlatList } from "react-native";
Thanks to #The1993, without the hint to compare the projects, maybe I would stuck forever on this error :D In the future I will compare working files to find any error!
contentContainerStyle is used to style inner content e.g items alignments, padding, etc
style is used to align its height and relations
You can replace style={{flex: 1}} instead of contentContainerStyle or wrap the parent element with flex: 1
I am using react native and firebase to create an application that's somewhat similar to a social network. In the profile screen I am trying to display the images that the user posted in a FlatList that has 3 columns. My problem is, when trying to display the images so that they occupy the full width of the FlatList, they don't seem to get displayed. However, when I set a fixed height, they do. I would like to make it so that they are shown with a 1/1 aspect ratio without having to fix a height.
This is my code:
<View style={styles.galleryContainer}>
<FlatList
numColumns={3}
horizontal={false}
data={posts}
renderItem={({ item }) => (
<View style={styles.imageContainer}>
<Image
style={styles.image}
source={{ uri: item.downloadURL }}
/>
</View>
)}
/>
</View>
And the styles:
galleryContainer: {
flex: 1
},
image: {
flex: 1,
aspectRatio: 1/1,
height: 120
},
imageContainer: {
flex: 1 / 3
}
I have tried setting the height to 100% and that did not work either, any ideas on what might be causing this?
Edit: I solved it by using useWindowDimensions and fetching the window size and dividing it by 3. This is the codethat I used to set the style:
const imageWidth = Math.floor(useWindowDimensions().width/3);
style={{width:imageWidth, aspectRatio:1/1, flex:1, height:imageWidth}}
I want to display multiple elements next to each other in React Native (with a flex wrap if there are too many elements or if the elements are too long). Each element consists of an icon and a text. If the text is too long, the text should break into the next line.
I tried different things with flexGrow and flexShrink but nothing had the desired effect. Here is my code (expo snack):
export default function App() {
function iconWithText(text) {
return (
<View style={styles.iconWithTextWrapper}>
<View style={{paddingRight: 10, backgroundColor: 'grey'}}>
<Text>Icon</Text>
</View>
<View style={{backgroundColor: 'yellow'}}>
<Text>{text}</Text>
</View>
</View>
)
}
return (
<View style={styles.container}>
{iconWithText('short text')}
{iconWithText('short text')}
{iconWithText('this is a long, long, long text that does break very ugly')}
</View>
);
}
const styles = StyleSheet.create({
container: {
marginTop: 50,
marginHorizontal: 50,
flex: 1,
flexDirection: 'row',
flexWrap: 'wrap',
justifyContent: 'flex-start',
},
iconWithTextWrapper: {
flexDirection: 'row',
margin: 10,
}
});
Here is the corresponding result - as you can see the margin of the whole container is not respected and the text does not break very well:
Why is the right margin of the container not respected, why does the text break like this and how can I fix this?
Try adding a flex:1 to your text style.
edit:
I played around in your snack and came up with this:
https://snack.expo.io/#moistbobo/iconwithtext
Please see if this fits your use case.
I need help fixing the overlap of views in my react native app (Need spacing between them).
After pressing the plus sign twice in top right corner, the two Views end up overlapping without any space between them (Which are called HoldWorkout Components)
Image of overlap
My App.js contains:
let PRs = PRArray.map((val, key) => {
return (
<HoldWorkout
key={key}
keyval={key}
val={val}
exName={setName}
setsHold={setSets}
/>
);
});
PRs is contained in the following Scroll View on Return:
<View style={styles.container}>
<View style={styles.whiteColor}>
<TouchableOpacity
activeOpacity={0.5}
onPress={addPR.bind(this)}
style={styles.TouchableOpacity}
>
<Icon name="ios-add" color="purple" size={45} />
</TouchableOpacity>
<View style={styles.header}>
<Text style={styles.headerTitle}>Personal Records</Text>
</View>
</View>
<ScrollView style={styles.scrollViewStyle}>
<View style={styles.color}>{PRs}</View>
</ScrollView>
</View>
The Styles in App.js is:
const styles = StyleSheet.create({
whiteColor: {
backgroundColor: "white",
borderBottomColor: "#F0EFF5",
borderBottomWidth: 2,
height: 80
},
container: {
flex: 1,
borderBottomColor: "#F0EFF5",
borderBottomWidth: 2
},
color: {
marginTop: 20,
backgroundColor: "#F0EFF5"
},
});
In HoldWorkout.js on return I have
<View key={props.keyval} style={styles.boxWorkouts}>
<TextInput
style={styles.input2}
placeholder="Excercise Name"
placeholderTextColor="#a9a9a9"
onChangeText={props.exName}
/>
<ExSets weight={setWeights} rep={setRep} date={setDates} />
{sets}
<View style={styles.addSet}>
<Button title="Add Set" color="purple" onPress={addSets}></Button>
</View>
</View>
The Style for the View is style.boxWorkouts which is in HoldWorkout.js and looks like
const styles = StyleSheet.create({
boxWorkouts: {
borderColor: "#BFBFBF",
borderWidth: 1,
backgroundColor: "white",
height: 90
}
});
I tried adding marginBottom: 100 to styles.boxWorkouts but that is fixed amount and if I click "Add Set" button on one of the HoldWorkout Components then it will add another row which will increase the height of the component and end up overlapping the component underneath it.
Image of after clicking Add Set on first Hold Workout Component with marginBottom set to 100
Please help on telling me how to fix the spacing for this as I have been trying to figure it out for a while because I am not sure how to get the components pushed down when I click "Add Set" button on the components above. This will ensure it wont overlap no matter how many times "Add Set" is pressed on the HoldWorkouts Components Above.
You need to add empty row or empty div with spacing as below.
let PRs = PRArray.map((val, key) => {
return (
<div>
<HoldWorkout
key={key}
keyval={key}
val={val}
exName={setName}
setsHold={setSets}
/>
<div> <br/> </div>
</div>
);
});
I`m working on a chat app and I use gifted chat .
I want my bubble to contain both text and an image. That works fine but I'm not satisfied with the way it is split...
I want to have text on the left and the image on the right side.
Currently, my text is above the image:
This is the code for the content of the bubble:
<TouchableOpacity key={i} style={[styles.mapView, this.props.mapViewStyle]}>
<View>
<Text style = {styles.titleText}> {title}</Text>
<Image style={[styles.image, this.props.imageStyle]} source={{uri: 'https://facebook.github.io/react/img/logo_og.png'}}/>
</View>
</TouchableOpacity>
Any ideas on how I can achieve text on the left and the image on the right?
You need flexDirection on View: https://facebook.github.io/react-native/docs/flexbox.html#flex-direction
The default value is column so children are stacked vertically.
You need to use flex in View https://facebook.github.io/react-native/docs/flexbox.html You can also give desired alignment to text and image. By default direction is column so use flexDirection:'row'
Use the code below.
<TouchableOpacity key={i} style={[styles.mapView, this.props.mapViewStyle]}>
<View style={{flex:1,flexDirection:'row'}}>
<View style={{flex:0.5}}>
<Text style = {styles.titleText}> {title}</Text>
</View>
<View style={{flex:0.5}}>
<Image style={[styles.image, this.props.imageStyle]} source={{uri: 'https://facebook.github.io/react/img/logo_og.png'}}/>
</View>
</View>
</TouchableOpacity>