I am using a FlatList to render an array on the screen. It works fine exception for one use case. The issue I am having is that when I have less than 4 items in a row then it renders differently.
Here is an example. I have 2 items in the second row. I would like it to fill the first two columns but it fills the first and third column.
What am I doing wrong here?
const data = [
{id:1, title: 'Option 1', image: require('../../assets/empty-profile-picture.jpeg')},
{id:1, title: 'Option 2', image: require('../../assets/empty-profile-picture.jpeg')},
{id:2, title: 'Option 3', image: require('../../assets/empty-profile-picture.jpeg')},
{id:3, title: 'Option 4', image: require('../../assets/empty-profile-picture.jpeg')},
{id:4, title: 'Option 4', image: require('../../assets/empty-profile-picture.jpeg')},
{id:5, title: 'Option 4', image: require('../../assets/empty-profile-picture.jpeg')}
, ];
<FlatList
contentContainerStyle={{ justifyContent: 'space-between' }}
data={data}
numColumns={4}
keyExtractor={(item) => item.id.toString() }
renderItem={({item, index}) => {
const lastItem = index === data.length - 1;
return (
<View style={{flex: 1, marginBottom: 20 }}>
<Image style={styles.cardImage} source={item.image} />
<Text style={styles.title}>{item.title}</Text>
</View>
);
}}
/>
EDIT
Changing the bottom part to this:
<View style={{flex: 1, marginBottom: 20, alignItems: 'flex-end', }}>
<Image style={styles(theme).cardImage} source={item.image} />
<Text style={styles(theme).title}>{item.title}</Text>
</View>
does seem to have some effect on the row and look this:
2
Answers
Remove justifyContent: ‘space-between’ inside the contentContainerStyle
for the spacing style apply on the main view of the return()
try them may be it’s working as per your requirement.
The reason why this happens is
numColumns={4}
. TheFlatList
component tries to split its data items evenly on4 columns
. The number6
is not evenly divisible by4
. The remainder is2
, so it makes room for two components that use the same space as the others.You can think of it as a grid. First, the number of items are calculated (in this case 6), then it is determined how many rows are needed (in this case 2). In summary, we get a
2x4 grid
and each cell in this grid gets the same amount of space. Second, it tries to distribute the actual items evenly among free cells, alternating empty cells and actually occupied cells. If we have 5 items instead of 6, you will notice, that it looks like you want.Solution: I haven’t found an elegant solution to this issue, i.e. some simple prop that we could use. However, we can calculate this ourselves and add a dummy view.
I have created a dummy array for testing:
The result is as follows and works dynamically for any number of elements.
Here is a little snack for testing.