9

I'm using FlatList from React Native to render a bunch of items stacked on top of each other.

This works fine, I've managed to make the FlatList itself expand it's height to fill the available space but I want the FlatList items to grow when there is more space available.

This was simple to do using ScrollView (simplified pseudocode):

<ScrollView
  contentContainerStyle={{
    display: "flex",
    flexGrow: 1,
  }}
>
  <Item key={1} style={{ flexGrow: 1 }} />
  <Item key={2} style={{ flexGrow: 1 }} />
</ScrollView>

However it doesn't work for FlatList (simplified pseudocode):

<FlatList
  contentContainerStyle={{
    display: "flex",
    flexGrow: 1,
  }}
  renderItem={({ index }) => <Item key={index} style={{ flexGrow: 1 }} />}
/>

I've created an Expo Snack showing both the ScrollView successfully growing the elements and the FlatList failing to do so.

There seems to be a lot of discussion online about making the parent FlatList full height, but I've struggled to find anything about making the FlatList items grow to fill the available FlatList height.

I need to use FlatList as I plan to use react-native-draggable-flatlist to implement drag and drop and cannot find an equivalent library that doesn't use FlatList.

A screenshot of the Expo Snack is shown here: Screenshot showing example of ScrollView items growing to fill available height but FlatList items failing to do the same

As seen here, it seems the offending issue in the DOM is the CallRenderer, the VirtualizedList is the right height with the right flex styling, and DayItem is set to grow (and worked fine with ScrollView), but in between there's the CallRenderer which seems to interrupt the flex relationship between the two:

Screenshot inspecting VirtualizedList Screenshot inspecting CallRenderer Screenshot inspecting FlatList child item

Any help is much appreciated.

fredrivett
  • 5,419
  • 3
  • 35
  • 48
  • If you set a minHeight: screen to the flatlist it might help with that – Craques Mar 20 '21 at 22:10
  • @Craques the `FlatList` itself is already growing to the height available, it's just the items inside that won't grow (despite parent being `flex` and the children being `flexGrow: 1`, seems `CallRenderer` is breaking the flex setup – fredrivett Mar 22 '21 at 08:50

3 Answers3

4

As a workaround, you can listen to onLayout of the Flatlist, hold the calculated height in a state, and then set each child's height to flatlist height / data.length.

angelos_lex
  • 1,593
  • 16
  • 24
  • hmm this could work with `minHeight` as a backup plan, hoping to fix it with CSS only but will bear in mind, thanks! – fredrivett Mar 22 '21 at 08:51
1

I found the best method to accomplishing this is to divide the height of the screen or in the case of your example the height of flatlist itself by the number of list items (or the number of items you would like to fill the screen at a time) and set that as the height of renderItem:

 const items = [ { text: "First item" }, { text: "Second item"} ];

 // height given to flatlist
 const FLATLIST_HEIGHT= 200;

 // or number of Items I want to fill screen
 const ITEMS_COUNT = items.length;

 const renderItem = ({ item, index, drag, isActive }) => {
    return (
      <View
        style={{
          borderWidth: 2,
          height: Math.floor(FLATLIST_HEIGHT/ITEMS_COUNT) - 2,
          // minus 2 to compensate for borderWidth
        }}
      >
        <Text>{item.text}</Text>
      </View>
    );
  };

...

 const myFlatList = (
    <FlatList
      data={items}
      renderItem={renderItem}
      keyExtractor={item => item.id}
      contentContainerStyle={{
        height: FLATLIST_HEIGHT,
      }}
    />
  );

In cases where no flatlist fills up the screen simply set the value of the window height:

import {..., Dimensions} from 'react-native';

...
const HEIGHT = Dimensions.get('window').height;

const renderItem = ({ item, index, drag, isActive }) => {
    return (
      <View
        style={{
          borderWidth: 2,
          height: Math.floor(HEIGHT/ITEMS_COUNT) - 2,
          // minus 2 to compensate for borderWidth
        }}
      >
        <Text>{item.text}</Text>
      </View>
    );
  };
user1738546
  • 619
  • 6
  • 15
0

make each item flex: 1 not the flatlist

TheEhsanSarshar
  • 2,677
  • 22
  • 41
  • thanks for the reply Ehsan, but the items already have `flexGrow: 1` on them, setting the shorthand `flex: 1` only sets `flexShrink` and `flexBasis` and when trying that out it doesn't make a difference here. can see the code here: https://snack.expo.io/@fredrivett/flex-flatlist-items-to-fill-height-not-working – fredrivett Mar 23 '21 at 10:53
  • seems strange? would you mind to please check the inner details of the flatlist you can figure it out how it works internally – TheEhsanSarshar Mar 23 '21 at 11:25
  • I think because of performance. flatlist always assign a calculated height for every item. – TheEhsanSarshar Mar 23 '21 at 11:57
  • one workaround is to divide number of item on the height of the flatlist – TheEhsanSarshar Mar 23 '21 at 11:58
  • or you can open an issue on github. – TheEhsanSarshar Mar 23 '21 at 12:00
  • yeah I agree it it probably by design for performance, but hadn't seen anything from my research mentioning this yet. I may have to open an issue on github but thought this was more of a question than a bug/limitation. will ask there too, cheers! – fredrivett Mar 23 '21 at 16:33