rubie
rubie

Reputation: 2246

React Native FlatList not scrolling to end

I've got (what I thought was) a simple FlatList which renders a list of Cards (code below)

Problem: the list renders, but won't scroll to fully display the last element in the list, OR to the content below the FlatList

What I've tried: basically everything in related SO questions:

Any ideas?

<FlatList
        data={props.filteredProducts}
        renderItem={({item}) => (
          <TouchableOpacity onPress={() => props.addItemToCart(item)}>
            <Card
              featuredTitle={item.key}
              image={require('../assets/icon.png')}
            />
          </TouchableOpacity>
        )}
        keyExtractor={item => item.key}
        ListHeaderComponent={
          <SearchBar />
        }
      />
<Other Stuff>

Upvotes: 44

Views: 56794

Answers (13)

Juanma
Juanma

Reputation: 706

Moving all styling from the FlatList view and adding a View as the main container worked for me.

<View style={{flex: 1, width: '100%', paddingVertical: 10, alignItems: 'center'}}>
    <FlatList 
        data={data}
        keyExtractor={item => item.code}
        renderItem={({ item }) => renderItem(item)}
        ListHeaderComponent={renderHeader}
    />
</View>

Inside my renderItem and renderHeader, I had an AutoHeightWebView component that was messing up my screen. Deleting all flex: 1 and keeping it only in the Flatlist's new view parent worked wonders!

Upvotes: 0

Hfajardo
Hfajardo

Reputation: 11

Try use to resolve the props ListFooterComponent

<FlatList
    data={data}
    renderItem={renderItems}
    ListFooterComponent={<View style={{height: 200}}/>}
/>

Upvotes: 0

Joseph Ajibodu
Joseph Ajibodu

Reputation: 1676

The ultimate solution is ✔

Any view/subview that holds a flatlist must have a flex of 1 - Regardless of how deep.

So if you apply this and it's not working, check your styling and make sure there's no mistake somewhere.

Upvotes: 14

Abdul Rashid
Abdul Rashid

Reputation: 11

use dimensions for parent view and set height as given:

const screenHeight = Dimensions.get('window').height - 100 
 <View style={{...styles.container,height:screenHeight}}>
 ....All child components
 </View>

Upvotes: 1

Vars Zakaryan
Vars Zakaryan

Reputation: 321

I had the same issue and just found the solution. Add the prop ListFooterComponentby giving it a React element/component. I just passed a view with the preferable height and it worked for me perfectly.

Here is the code snippet:

<FlatList
        data={DATA}
        renderItem={({ item }) => (<ListItem itemData={item} />) }
        keyExtractor={item => item.id}
        ListFooterComponent={<View style={{height: 20}}/>}
      />

This works 100%!

Upvotes: 23

Meo Flute
Meo Flute

Reputation: 1301

I had the same problem. What I did was to provide a marginBottom to the parent view of the FlatList with size that is equivalent (or a little larger) than the size of the rendered item .

<View style={{marginBottom: HEIGHT_OF_CELL + 60, flexGrow:1}}>
    <FlatList
         keyExtractor={(item, index) => index.toString()}
         data={posts}
         renderItem={renderItem}
    />
            
</View>
        

Upvotes: 2

Wilfred Mulenga
Wilfred Mulenga

Reputation: 398

I method I used to resolve this is by setting the parent view to the FlatList's background color to a visible color(e.g red). Then adjust the margin bottom for that view so that it is large enough for all the contents in the FlatList to be viewed.

In my case the parent view was wrapped in another view which I could not give the flex: 1 style to.

Upvotes: 1

Add flex: 1 to child into renderItem

<View style={{ height: `93%` }}>
  <FlatList
    contentContainerStyle={{ minHeight: `100%` }}
    scrollEnabled={true}
    ...props
    renderItem={({item}) => (
      <View style={{ flex: 1 }}>
        ...
      </View>
    )}

Upvotes: 3

Lima Neto
Lima Neto

Reputation: 53

Remove flex:1 from the FlatList and leave only the parent View.

Upvotes: 3

Eugene P.
Eugene P.

Reputation: 1833

Add style={{flex: 1}} for each View element who is a parent for FlatList.

Upvotes: 107

nipek
nipek

Reputation: 850

adding flex:1 to my render item worked for me

 <FlatList
      data={data}
      renderItem={({ item }) => (
        <ListItem
          onPress={() => console.log('ok')}
          bottomDivider
          rightTitle={
            <Divider style={{ marginBottom: 4, backgroundColor: item.status, width: '50%', height: '11%', borderRadius: 10 }} />
          }
          titleProps={{ numberOfLines: 1 }}

          rightSubtitle={item.date}
          rightTitleStyle={{ fontFamily: 'poppins' }}
          rightSubtitleStyle={{ fontFamily: 'poppins' }}
          titleStyle={{ fontFamily: 'poppins' }}
          subtitleStyle={{ fontFamily: 'poppins' }}
          title={item.device}
          subtitle={item.type}
          leftAvatar={{ source: item.icon, rounded: false }}
          **style={{ flex: 1 }}**
        />
      )}
      keyExtractor={item => item._id}
      ListHeaderComponent={renderHeader}
      ListFooterComponent={renderFooter}
      onEndReached={handleLoadMore}
      onEndReachedThreshold={0.2}

    />

Upvotes: 0

Brian Hong
Brian Hong

Reputation: 1084

My case is a little different, in that I used FlatList inside bottom sheet provided by reanimated-bottom-sheet package. But the problem was the same: scrolling didn't show the last item properly.

The way I did was I calculated and set the height of the view that included the FlatList. To make it look better when there is bottom inset, I gave more bottom margin to the last item of the FlatList by doing like this:

<FlatList
    data={results}
    keyExtractor={(item) => item.name}
    scrollEnabled={bottomSheetIndex == 1 ? true : false}
    renderItem={({ item }) =>
        <LocationInfo
            bottom={results[results.length - 1].id == item.id ? insets.bottom : 0}
            result={item}
            wait={waitState[item.id]}
            bsIndex={bottomSheetIndex}
        />
    }
/>

const LocationInfo = ({ bottom, result, wait, bsIndex }) => {

    return (
        <View style={[styles.container, { paddingBottom: bottom }]}>
            ... 

for insets, see react-native-safe-area-context.

Upvotes: 4

Nnanyielugo
Nnanyielugo

Reputation: 403

I'm not sure if your scenario is exactly the same as one I encountered on a project a few months ago, but I noticed that I had to add a margin/padding (depends on what you prefer) to lift the bottom of the scrollable container. This was usually because a parent container seemed to interfere with the styling of the scrollable element.

Have you tried adding flexGrow: 1 to your styling in place of flex?

Upvotes: 4

Related Questions