Display images in FlatList

Ivan Burzakovskiy picture Ivan Burzakovskiy · Jan 4, 2019 · Viewed 17.6k times · Source

I'm trying to render images in grid view using FlatListbut have faced with the next issue:

My code snippet:

...
renderItem = ({item}) => {
        return (
        <Image source = {{uri: item.photoUrl[0].photoUrl}} style = {{margin: 1,
                                                                    height: Dimensions.get('window').width / 3,
                                                                    width: Dimensions.get('window').width / 3,
                                                                    resizeMode: 'cover'}}
        />
    )
}

render() {
    if(this.props.viewOption === 'grid') {
        return <FlatList
                    data = {this.state.photosKeysArray}
                    keyExtractor={(item, index) => item.id}
                    numColumns = {3}
                    renderItem={this.renderItem}
                />
    } ...

Problem is that FlatList should calculate width of item by itself according to numColumns, right? So in Image I should specify only height. Since I want to render square images, I assign to height a value equals to Dimensions.get('window').width/3, where 3 is value of numColumns.

After that FlatList renders blank spaces instead of images.

If I add width property to Image (like in my code snippet) and define it as height (square image, remember?) then FlatList renders 3 columns with square images but they are show like on my sketch (two full images and the last column is cut):

enter image description here

How to show three full columns?

Answer

ValdaXD picture ValdaXD · Jan 4, 2019

Do you want easy squares? , ok then you should know this property that react native has, it's called Aspect Ratio , you just set the width or height, set the aspect ratio to 1 in style and you have an square.

This stays the same

<FlatList
   numColumns={3}
   data={this.state.data}
   renderItem={({ item }) => this.renderItem(item)}
/>

but this is more simple

renderItem(item) {
    return (
        <TouchableOpacity  
                 style={{flex:1/3, //here you can use flex:1 also
                 aspectRatio:1}}>
                <Image style={{flex: 1}} resizeMode='cover' source={{ uri:  item.photoUrl[0].photoUrl}}></Image>
        </TouchableOpacity>
    )
}

It shoud be noted that if you have an extra item below all the rows, and you use flex:1 instead of flex:1/3 it's gonna be a big , really big square, for that you can use the methods described here