38

Hi i'm new in React Native.

I am trying to create two columns layout with space beetween using react native component called flatList.

Here is my view Code:

<View style={styles.container}>
        <FlatList
            data={db}
            keyExtractor={ (item, index) => item.id }
            numColumns={2}
            renderItem={
                ({item}) => (
                    <TouchableWithoutFeedback  onPress ={() => showItemDetails(item.id)}>
                        <View style={styles.listItem}>
                            <Text style={styles.title}>{item.name}</Text>
                            <Image
                                style={styles.image}
                                source={{uri: item.image}}
                            />
                            <Text style={styles.price}>{item.price} zł</Text>
                        </View>
                    </TouchableWithoutFeedback>
                )
            }
        />
    </View>

Here is styles:

container: {
    flex: 1,
    flexDirection: 'row',
    justifyContent: 'space-between',
    padding: 10,
    marginBottom: 40
},
listItem: {
    maxWidth: Dimensions.get('window').width /2,
    flex:0.5,
    backgroundColor: '#fff',
    marginBottom: 10,
    borderRadius: 4,
},

And result is two columns but without space between. Could you help me resolve this problem ?

10 Answers 10

78

You can give the item itself a width value of 45%. Also, flatlist has a property called columnWrapperStyle that you can give the value justifyContent: 'space-between.

Heres an example:

<FlatList
    columnWrapperStyle={{justifyContent: 'space-between'}}
    data={ApiData}
    numColumns={2}
    renderItem={({item}) => {
      return (
         <item style={{width: '45%'}} />
      );
    }}
/>
3
  • Not working using columnWrapperStyle={{justifyContent: 'space-between'}} Commented Nov 2, 2020 at 6:34
  • 1
    did you give the item it self a width of 45% for example
    – Eslam Adel
    Commented Nov 3, 2020 at 10:48
  • For me, space-around looks better than space-between.
    – Murtuza
    Commented Jul 24, 2021 at 9:38
42

Use ItemSeparatorComponent for render a compontent between items

Docs: Rendered in between each item, but not at the top or bottom.

    <FlatList
        data={arrayOfData}
        horizontal
        ItemSeparatorComponent={
            () => <View style={{ width: 16, backgroundColor: 'pink' }}/>
        }
        renderItem={({ item }) => (
            <ItemView product={item} />
        )}
    />

Preview in horizontal list enter image description here

If list is vertical and suppose columnCount is 2

enter image description here

15

You have to give the styles.container to the contentContainerStyle propety of Flatlist, like so:

<FlatList
        data={db}
        keyExtractor={ (item, index) => item.id }
        contentContainerStyle={styles.container}
        numColumns={2}
        renderItem={
            ({item}) => (
                <TouchableWithoutFeedback  onPress ={() => showItemDetails(item.id)}>
                    <View style={styles.listItem}>
                        <Text style={styles.title}>{item.name}</Text>
                        <Image
                            style={styles.image}
                            source={{uri: item.image}}
                        />
                        <Text style={styles.price}>{item.price} zł</Text>
                    </View>
                </TouchableWithoutFeedback>
            )
        }
    />
1
  • Also make sure horizontal={true} is not defined in <FlatList>
    – Joe McLean
    Commented May 19, 2022 at 1:58
10

How to create two columns with equal spacing between items:

    <FlatList 
        data={DATA}
        renderItem={renderItem}
        keyExtractor={(item) => item.id}
        horizontal={false}   // you must include this line when using numColumns [per the documentation][1]
        numColumns={2}   // creates two columns
        key={2}   // add key to prevent error from being thrown
        columnWrapperStyle={{justifyContent: 'space-between'}}   // causes items to be equally spaced
    >

Also, this will set each column to 1/2 the screen width:

const styles = StyleSheet.create({
item: {
      flex: 1/2,
}})
1
  • Just adding columnWrapperStyle={{justifyContent: 'space-between'}} does it for me. Commented Jan 31, 2024 at 3:04
3

Just add some margin to the style of the list Item.

listItem: {
  margin: 10,
}
1
  • This will mess with flatList scrolling offset, thus producing a scrollable list that can't scroll to the bottom of the content. Commented Jan 5, 2018 at 17:21
1

Based on your example it looks like you can add a margin to your list item styles:

listItem: {
    maxWidth: Dimensions.get('window').width /2,
    flex:0.5,
    backgroundColor: '#fff',
    marginBottom: 10,
    borderRadius: 4,
    margin: 18,
},

Keep in mind that this is equivalent to doing:

listItem: {
    maxWidth: Dimensions.get('window').width /2,
    flex:0.5,
    backgroundColor: '#fff',
    marginBottom: 10,
    borderRadius: 4,
    marginTop: 18,
    marginBottom: 18,
    marginRight: 18,
    marginLeft: 18,
},

Customize to your liking or spec :)

1

You can do this by adding the flex property gap in columnWrapperStyle

<View style={styles.container}>
    <FlatList
        columnWrapperStyle={{gap:5}}
        data={db}
        keyExtractor={ (item, index) => item.id }
        numColumns={2}
        renderItem={
            ({item}) => (
                <TouchableWithoutFeedback  onPress ={() => showItemDetails(item.id)}>
                    <View style={styles.listItem}>
                        <Text style={styles.title}>{item.name}</Text>
                        <Image
                            style={styles.image}
                            source={{uri: item.image}}
                        />
                        <Text style={styles.price}>{item.price} zł</Text>
                    </View>
                </TouchableWithoutFeedback>
            )
        }
    />
</View>
0

Assuming your items are flex:1 and no width specified. You can wrap your renderItem with another view that adds the padding if needed


function columnWrappedRenderItemFunction<ItemT>(
  renderItem: ListRenderItem<ItemT>,
  numColumns: number,
  space: FlatListProps<ItemT>["space"],
  numberOfItems: number
): FlatListProps<ItemT>["renderItem"] {
  return function columnWrappedRenderItem({
    index,
    ...props
  }: Parameters<ListRenderItem<ItemT>>[0]): ReturnType<ListRenderItem<ItemT>> {
    const needsGapOnLeft = index % numColumns !== 0;
    let extraItems = 0;
    if (index === numberOfItems - 1) {
      extraItems = (numColumns - (numberOfItems % numColumns)) % numColumns;
    }
    if (needsGapOnLeft) {
      return (
        <>
          <View style={{width:space}} />
          {renderItem({ index, ...props })}
          {Array.from({ length: extraItems }, (_, k) => (
            <View key={"extra_" + k} style={{marginLeft:space, flex:1}} />
          ))}
        </>
      );
    } else {
      return (
        <>
          {renderItem({ index, ...props })}
          {Array.from({ length: extraItems }, (_, k) => (
            <View key={"extra_" + k} marginLeft={space} style={{flex:1}} />
          ))}
        </>
      );
    }
  };
}

e.g.

function myRenderItem() { ... }
...
return (<FlatList 
   ...
   data={data}
   renderItem={
     numColumns === 1
          ? renderItem
          : columnWrappedRenderItemFunction(
              renderItem,
              numColumns,
              space,
              data.length
            )
      }
   numColumns={numColumns}
   ItemSeparatorComponent={() => <View style={{height: space}} />}
  />);
0

You can do this by adding the flex property gap in columnWrapperStyle

<FlatList
                data={data}
                columnWrapperStyle={{gap:s(5)}}
                renderItem={({ item }) => (
                  <View
                    style={{
                      flex: 1,
                      alignItems: "center",
                      gap: s(8),
                      flexDirection: "row",
                    }}
                  >
                    
                  </View>
                )}
                ItemSeparatorComponent={({ item, index }) => (
                  <View
                    style={{
                      marginVertical: s(5), //Add space between rows
                    }}
                  />
                )}
                numColumns={2}
                keyExtractor={(item, index) => index.toString()}
              />

-1

I haven't used this library, but adding padding: 10 to listItem styles should help.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.