Ripas55
Ripas55

Reputation: 943

How do I add gap in between items in flatlist?

I want to add some spacing in react native using flatlist, but it seems more difficult than it should be at the moment.

Turns out that react native does not support gap property, which makes this very complicated.

I solved the horizontal spacing, by making my item 49.5% wide which means I have 1% space horizontally, now how do I do the same for vertical spacing?

Most importantly how do i ensure that both horizontal and vertical "gaps" are EQUAL.

const renderItem = ({ item }) => (
  <Pressable onPress={() => alert(item.name)} style={{
        aspectRatio: 1,
    width: "49.5%",
    position: "relative",
  }}>
    <Image
      style={{
        width: "100%",
        height: "100%"
      }}
      source={{
        uri: item.url,
      }}
    />
    <View
      style={{
        position: "absolute",
        zIndex: 3,
        bottom: 0,
        paddingHorizontal: 2,
        paddingVertical: 8,
        flexDirection: "row",
        // justifyContent: "center",
        alignItems: "center",
      }}
    >
      <Text style={{ color: "white", fontSize: 16 }}>{item.name}</Text>
    </View>
  </Pressable>
);

export default function App() {
  return       <FlatList
        numColumns={2}
        data={people}
        renderItem={renderItem}
        columnWrapperStyle={{
          justifyContent: "space-between"
        }}       
      />
}

enter image description here

Upvotes: 27

Views: 45651

Answers (7)

krlsdgzmn
krlsdgzmn

Reputation: 1

If you're using NativeWind, this works:

 <FlatList
    contentContainerClassName="gap-2"
    ...
  />

Upvotes: 0

marcel099
marcel099

Reputation: 576

Update

As Antonio Jaime stated in his answer, since RN 0.71 released in January 2023 there is a more clever and straightforward way to do it: gap in contentContainerStyle and columnWrapperStyle. Please check it out.

Previous Answer

You could use the ItemSeparatorComponent property of the FlatList component to make the vertical gap. This property is a component rendered in between each FlatList item, but not at the top, bottom, right or left. You can read more about it on the documentation.

Change the FlatList to this:

<FlatList
  numColumns={2}
  data={people}
  renderItem={renderItem}
  ItemSeparatorComponent={() => <View style={{height: 20}} />}
  /* that is not necessary anymore
columnWrapperStyle={{
    justifyContent: "space-between"
  }} */      
/>

In order for the horizontal space to be given the same size as the vertical space, you can move one column away from the other using padding:

  • The items on the left have a paddingRight of half the size of the vertical space.
  • The ones on the right get paddingLeft instead of paddingRight.

Here's the code:

const renderItem = ({ item, index }: Props) => (
  <View
    style={[
      {
        aspectRatio: 1,
        flexGrow: 1,
        width: "50%",
        position: "relative",
      },
      index % 2 === 0
      ? {
        paddingRight: 10,
      } : {
        paddingLeft: 10
      }
    ]}
  >
    <Pressable
      onPress={() => alert(item.name)}
    >

Some points:

  • A parent View component was created because if the Pressable had the padding property, the vertical gap would be pressable too.
  • Don't forget to set width: '50%' because this makes the images took half the screen's width.
  • Both sides should receive the same padding value because this is important to make the gap centered.
  • You should use padding instead of margin because the width still is 50%, so margin would push the elements beyond the right edge of the screen. If you use a greater value like 40 instead of 10 and margin instead of padding you can see the problem.

This was the visual result.

P.S.: I ran your app in my machine with some URL images I got on Unsplash and it worked: the vertical gap was created by the ItemSeparatorComponent.

P.S. 2: I made some changes to the code and now both horizontal and vertical gaps are equal sized. This was the result. In addition, I changed my answer.

Upvotes: 41

Amil Aliyev
Amil Aliyev

Reputation: 31

A bit late to the party but currently a simple gap is working for me:

<FlatList contentContainerStyle={{ gap: 16 }} />

Upvotes: 3

Antonio Jaime
Antonio Jaime

Reputation: 589

If you're on RN >=0.71 and you want more control over the spacing between columns and items, you can also use the gap styling property on contentContainerStyle and columnWrapperStyle like so:

<FlatList
  // 👇
  contentContainerStyle={{ gap: GAP_BETWEEN_ROWS }}
  columnWrapperStyle={{ gap: GAP_BETWEEN_COLUMNS }}
  numColumns={2}
  // 👆
  data={data}
  renderItem={renderItem}
/>

Upvotes: 32

JonathanBav
JonathanBav

Reputation: 1

to add gap between items in a Flatlist, the best way to do it, is to add columnWrapperStyle prop and passing in justifyContent: 'space-between. so the space between two or more items horizontally, vertically you can just use marginBottom on the items. or if you want to use an illusion of spacing, you can use a white border around item items, that will make it look like there is spacing between them.

hope this helps

<FlatList columnWrapperStyle={{ justifyContent: 'space-between' }} />

Upvotes: 0

oldo.nicho
oldo.nicho

Reputation: 2289

Simple solution for me was to just added margin around each item and negative margin around container.

Upvotes: 3

David Scholz
David Scholz

Reputation: 9856

The ItemSeparatorComponent takes care of the space between rows but not between columns. Since we have a two column FlatList, we can create the same space as provided by the ItemSeparatorComponent between two columns by adding it as a marginRight to all the elements that have an odd index.

<FlatList
   numColumns={2}
   data={people}
   ItemSeparatorComponent={() => <View style={{height: 10}} />}
   renderItem={({index, item}) =>  (
        <Pressable onPress={() => alert(item.name)} style={{
             aspectRatio: 1,
             width: "49.5%",
             marginRight: index % 2 !== 0 ? 0 : 10,             
             position: "relative",
        }}>
            ...

         </Pressable>})
/>

The key part is the marginRight: index % 2 !== 0 ? 0 : 10 for the parent view of each item in the render function.

Upvotes: 7

Related Questions