React Native FlatList last item visibility issue

React NativeReact Native-Flatlist

React Native Problem Overview


I am fetching products list and then displaying using a FlatList, my list contains 5 items and as you can see FlatList row height is variable because of varying description text. So the issue is my last item card is not completely visible maybe this is some kind of flat list issue or layout issue. Any help would be highly appreciated

 renderProducts() {
        if (this.props.loading === true) {
            return (
                <View style={Styles.spinnerStyle}>
                    <ActivityIndicator size='large' />
                </View>
            );
        }

        return (
                <FlatList
                    data={this.props.myProducts}
                    keyExtractor={(item) => item.id}
                    renderItem={({ item }) => (
                        <Card 
                            title={item.title} 
                            image={{ 
                                uri: item.image !== null ? item.image.src :'../resImage.jpg' 
                            }}
                        >
                            <Text style={{ marginBottom: 10 }}>
                                {item.body_html}
                            </Text>
                            <Button
                                icon={{ name: 'code' }}
                                backgroundColor='#03A9F4'
                                fontFamily='Lato'
                                buttonStyle={{ borderRadius: 0, marginLeft: 0, marginRight: 0, marginBottom: 0 }}
                                title='VIEW NOW' 
                            />
                      </Card>
                      )}
                />
        );
    }
    
    render() {
        return (
            <View>
                <View style={Styles.viewStyle}>
                    <Text style    {Styles.textStyle}>ProductsList</Text>
                </View>
                    { 
                        this.renderProducts() 
                    }
            </View>
        );
    }

React Native Solutions


Solution 1 - React Native

Set bottom padding to the <FlatList> content container:

<FlatList
    contentContainerStyle={{ paddingBottom: 20 }}
/>

Solution 2 - React Native

Add {flex: 1} to the View tag housing the Flatlist component.

In my case,

const App = () => {
  return (
    <Provider store={createStore(reducers)}>
    <View style={{ flex: 1 }}>
      <Header headerText={'My App'} />
      <ScreenTabs /> // this is my content with FlatList 
    </View>
    </Provider>
  );
};

export default App;

Solution 3 - React Native

Just wrap it in a view with flex:1

<ParentView style={{flex:1}
    <View style={{flex:1}}>
    // Your flatlist
    <View>
</ParentView>

Also, note that the each parent of this "View" in which Flatlist is wrapped must also be a View with Flex of 1. Otherwise, that your flatlist wont be visible.

Solution 4 - React Native

use contentContainerStyle props of FlatList

<FlatList contentContainerStyle={{ paddingBottom: 20}} />

Solution 5 - React Native

Latest update:

react-navigation has a SafeAreaView with an option to not show that bottom area.

import { SafeAreaView } from 'react-navigation';
<SafeAreaView forceInset={{ bottom: 'never' }} />

Old response below:

You can't see your list with flex: 1 because flex: 1 will grow the component to the parent. If the parent doesn't have flex: 1, it won't stretch to its parent or the screen. Keep in mind, however, that flex: 1 with a SafeAreaView will cause the bottom safe area to show. This will look bad if your SafeAreaView backgroundColor is a different color from your list's back ground.

My old workaround was to add an item to the bottom of the array of items, but I'm still exploring how to scroll past/under the bottom safe area margin with a FlatList (which is how I found this post to begin with).

Update: Using ListFooterComponent you can create even a plain white "footer" with height and/or a margin

For example (I wouldn't directly copy and paste this if I were you... there's surely a better way to detect bezel-less iPhones, especially in 2019 when we have more than one)

ListFooterComponent={<View style={{ height: 0, marginBottom: 90 }}></View>}

This is how I would do it, using the iPhoneX's height for now. But it's not future-proof since the conditional will need to be updated every time a new iPhone with no bezels comes out:

ListFooterComponent={<View style={{ height: 0, marginBottom: noBezels ? 90 : 0 }}></View>}

Or you could just always have some spacing at the bottom, like a loading gif, a message... whatever.

UPDATE 2:

I found out about react-native-device-info which has a hasNotch() method. I find that useful for styling for iPhones with no bezels by combining hasNotch() with Platform.OS === 'ios'

Solution 6 - React Native

You can try this solution

For Vertical FlatList:

<FlatList
 ListFooterComponent={<View />}
 ListFooterComponentStyle={{height:200}}
/>

For Horizontal FlatList:

<FlatList
  contentContainerStyle={{paddingRight:40}}
/>

Solution 7 - React Native

For IOS issues you can apply some IOS specific props:

<FlatList
  // ...
  contentInset={{top: 0, bottom: 20, left: 0, right: 0}}
  contentInsetAdjustmentBehavior="automatic"
  // ...  
/>

The solution with contentContainerStyle padding didn't seem the best overall for fixing the safe area IOS issues in my case.

Solution 8 - React Native

Make use of the contentContainerStyle prop in the flatlist <FlatList contentContainerStyle={{paddingBottom: 10}} />

Solution 9 - React Native

Work very well for me

<FlatList
  data={data}
  contentContainerStyle={{ paddingBottom: 30 }}
  style={{height: '95%'}}
  renderItem={({ item, index }) => (
    <ListItem item={item} onPress={() => handlePress(item, index)} />
  )}
/>

Solution 10 - React Native

I was seeing this same problem in our Android + iOS React Native hybrid app. We embed the FlatList component within our native UIs inside a Fragment in Android and we were unable to scroll to the last item in the list, even though the scroll indicator would show that there was more to scroll, the ScrollView would simply not scroll further. I tried all the combinations of using a wrapping <View style={{flex:1}}> to wrap the FlatList as well as using contentContainerStyle={{flexGrow:1}} on the FlatList without success. Pursuing the clue further it turned out that the FlatList needs an absolute, predefined height on Android to allow scroll to the bottom - it works just fine on iOS but on Android using match_parent wasn't going to work. Since we need to support all types of devices, phone and tablet too, it wasn't possible to pre-define an absolute height either.

To fix this, I made a custom FrameLayout subclass to house the ReactRootView's fragment, which overrides onLayout() to ignore the child view measurements, forcing the views to have the exact dimensions of the FrameLayout, somewhat like so in Kotlin:

class StretchFrameLayout @JvmOverloads constructor(
        context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {

    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
        for (child in children){
            if (child.visibility == View.GONE) continue
            child.updateLayoutParams {
                this.width = measuredWidth
                this.height = measuredHeight
            }
            if (needsRelayout){
                handler.postDelayed({child.requestLayout()},1)
            }
        }
        super.onLayout(changed, left, top, right, bottom)
    }
}

Solution 11 - React Native

This worked for me.

<View style={{flex: 1}}>
    <FlatList
      style={{flex: 1}}
      data={data}
      renderItem={({item}) => (
        <ListItem item={item} onPress={() => handlePress(item)} />
      )}
    />
  </View>

Solution 12 - React Native

This work very well in my case:

  <FlatList
    data={todos}
    contentContainerStyle={{ height: '100%' }}
    renderItem={({ item }) => <Todos items={item} pressed={pressed} />}
  />

Solution 13 - React Native

I've solved it doing contentInset={{ bottom: data.length * itemStyle.height, }} with itemStyle.height being 50 worked fine.

Solution 14 - React Native

@krish solution is great for the fixed-size list items, however as @Neeraj Sewani said, it may not be suitable for dynamic size list items.

so you can fix the issue like this -in case direction is column -:

<View  style={{height: '90%'}}> 
<FlatList/> 
</View>

Otherwise, -in case direction is row -:

<View  style={{height: '90%', width:'90%'}}> 
<FlatList/> 
</View>

Solution 15 - React Native

For dynamic flatlist, you can assign height to the parent view. I resolved it with same.

<View style={{height:'80%'}}>
  <Flatlist
    extraData={data}
    data={data}
    renderItem={renderItem}
  />
</View>

Solution 16 - React Native

I had the same issue and found the solution. To fix the issue just add style={{flex: 1}} for each View element who is a parent for FlatList.

See updated code below.

    render() {
        return (
            <View style={{flex: 1}}> // Here you should add style as {flex: 1}
                <View style={Styles.viewStyle}>
                    <Text style={Styles.textStyle}>ProductsList</Text>
                </View>
                { this.renderProducts() }
            </View>
        );
    }

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMuhammad TalhaView Question on Stackoverflow
Solution 1 - React NativekrishView Answer on Stackoverflow
Solution 2 - React NativeAshishView Answer on Stackoverflow
Solution 3 - React NativeAmitView Answer on Stackoverflow
Solution 4 - React NativeS.MahdiView Answer on Stackoverflow
Solution 5 - React NativejsonpView Answer on Stackoverflow
Solution 6 - React NativejamalView Answer on Stackoverflow
Solution 7 - React NativeFlorin DobreView Answer on Stackoverflow
Solution 8 - React NativeIchoku ChinonsoView Answer on Stackoverflow
Solution 9 - React NativePedro IvoView Answer on Stackoverflow
Solution 10 - React NativeDhiraj GuptaView Answer on Stackoverflow
Solution 11 - React NativeSuleiman AbdulMajeedView Answer on Stackoverflow
Solution 12 - React Nativeabdul basitView Answer on Stackoverflow
Solution 13 - React NativeEstebanView Answer on Stackoverflow
Solution 14 - React NativeJoseph AliView Answer on Stackoverflow
Solution 15 - React NativeVintiView Answer on Stackoverflow
Solution 16 - React NativePrasadView Answer on Stackoverflow