Search code examples
javascriptreact-nativereact-native-flatlistflatlist

FlatList exceeds its container with its content: How to make FlatList with fixed height


I have a <FlatList />. Within this <FlatList /> I have another <FlatList />. The nested <FlatList /> gives me some odd behavior. It exceeds the margins of its container. As you can see, the Flags are going over the yellow box, which represent the bounds of the <FlatList />.

Here is a Snack https://snack.expo.dev/@stophfacee/nested-flatlist which reproduces the problem.

Please note: The animation (when touching the hotpink rectangle) does not work properly. I am not sure why. However, I still included it because I am not sure if that might be the problem.


Solution

  • This might be the result you wanted. Please check this once!

    import React, { useState } from 'react';
    import {
      View,
      StyleSheet,
      Animated,
      Dimensions,
      TouchableOpacity,
      Text,
      ScrollView,
    } from 'react-native';
    import Constants from 'expo-constants';
    import CountryFlag from 'react-native-country-flag';
    import { FlatList } from 'react-native-gesture-handler';
    
    export default function App() {
      const _renderFlag = (country) => {
        return (
          <TouchableOpacity onPress={() => console.log('Flag touched')}>
            <CountryFlag
              isoCode={'NZ'}
              size={50}
              style={{ alignSelf: 'flex-end' }}
            />
          </TouchableOpacity>
        );
      };
    
      const _createCard = (card, index) => {
        return (
          <View style={styles.card} key={index}>
            <TouchableOpacity
              style={styles.touchable}
              onPress={() => console.log('toggle')}>
              <Text>{card}</Text>
            </TouchableOpacity>
            <View style={{ height: 200 }}>
              <FlatList
                nestedScrollEnabled={true}
                style={{ marginTop: 20, backgroundColor: 'yellow' }}
                columnWrapperStyle={{
                  justifyContent: 'space-around',
                }}
                ItemSeparatorComponent={() => <View style={{ margin: 10 }}/>}
                numColumns={3}
                data={[
                  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
                ]}
                renderItem={_renderFlag}
                keyExtractor={(item, index) => index.toString()}
                getItemLayout={(data, index) => ({
                  length: 50,
                  offset: 50 * index,
                  index,
                })}
              />
            </View>
          </View>
        );
      };
    
      return (
        <View style={{ flex: 1 }}>
          <FlatList
            style={{ margin: 20 }}
            data={['a', 'b', 'c']}
            keyExtractor={(item, index) => index.toString()}
            renderItem={({ item, index }) => _createCard(item, index)}
          />
        </View>
      );
    }
    
    const styles = StyleSheet.create({
      card: {
        borderColor: 'red',
        borderWidth: 2,
        padding: 8,
        marginBottom: 15,
      },
      touchable: {
        backgroundColor: 'hotpink',
        height: 50,
        width: '100%',
        justifyContent: 'center',
        alignItems: 'center',
      },
    });
    

    Working Example