skip to Main Content

I have a container that has a scrollview component nested inside that is also a container. Inside the scrollview container, I am looping through data and then trying to make the children be 2 items per row and also fill in any remaining empty space automatically, however, it will only fill up half the parent container.

enter image description here

I would like the 6 boxes shown in the image to evenly distribute the height and fill in the remaining space in the container.

// React Native Element

  return (
    <SafeAreaView style={[{ flex: 1 }]}>
      <ScrollView
        contentContainerStyle={surveyScreenStyles().cardsContainer}
      >
        <View
          style={[surveyScreenStyles().cardsContainer]}
        >
          {surveyData?.surveys?.map((surveyDetails, i) => (
            <Card
              key={`suvey-card-${i}`}
              mode='elevated'
              style={[surveyScreenStyles().cards]}
            >
              <Card.Title
                title={surveyDetails.name}
                titleVariant='titleLarge'
                subtitle={surveyDetails.summary}
                subtitleNumberOfLines={2}
              />
            </Card>
          ))}
        </View>
      </ScrollView>
    </SafeAreaView>
  );
}
// css file
{
    cardsContainer: {
      backgroundColor: "#FFFFFF",
      justifyContent: 'space-evenly',
      flex: 1,
      flexWrap: 'wrap',
      flexDirection: 'row',
      padding: 5,
      gap: 10
    },
    cards: {
      backgroundColor: "#FFFFFF",
      borderRadius: 10,
      flexBasis: '45%',
      justifyContent: 'center',
      padding: 10,
    }
}

2

Answers


  1. It looks like the flexWrap might be what is messing this up. I think because of the scroll view that doesn’t work quite how it should.

    Here is a solution that doesn’t look as clean as yours but has the desired result:

        <ScrollView
          contentContainerStyle={{
            flex: 1,
            flexDirection: 'column',
            padding: 5,
            gap: 10,
          }}
        >
          <View style={{ flex: 1, flexDirection: 'row', gap: 10 }}>
            <View
              style={{
                backgroundColor: '#FFFFFF',
                borderRadius: 10,
                justifyContent: 'center',
                padding: 10,
                flex: 1,
              }}
            ></View>
            <View
              style={{
                backgroundColor: '#FFFFFF',
                borderRadius: 10,
                justifyContent: 'center',
                padding: 10,
                flex: 1,
              }}
            ></View>
          </View>
          <View style={{ flex: 1, flexDirection: 'row', gap: 10 }}>
            <View
              style={{
                backgroundColor: '#FFFFFF',
                borderRadius: 10,
                justifyContent: 'center',
                padding: 10,
                flex: 1,
              }}
            ></View>
            <View
              style={{
                backgroundColor: '#FFFFFF',
                borderRadius: 10,
                justifyContent: 'center',
                padding: 10,
                flex: 1,
              }}
            ></View>
          </View>
          <View style={{ flex: 1, flexDirection: 'row', gap: 10 }}>
            <View
              style={{
                backgroundColor: '#FFFFFF',
                borderRadius: 10,
                justifyContent: 'center',
                padding: 10,
                flex: 1,
              }}
            ></View>
            <View
              style={{
                backgroundColor: '#FFFFFF',
                borderRadius: 10,
                justifyContent: 'center',
                padding: 10,
                flex: 1,
              }}
            ></View>
          </View>
        </ScrollView>
    
    Login or Signup to reply.
  2. If you use a flatlist, you can use the numColumns prop and the columnWrapperStyle prop to get 2 columns with your desired spacing styles. Then to get the items to take up the remaining height you can use the onLayout prop to get the height and then divide by 3, since there are 2 items per row:

    import {
      View,
      StyleSheet,
      ScrollView,
      SafeAreaView,
      FlatList,
      Image,
    } from 'react-native';
    import { Text, Card } from 'react-native-paper';
    import { useState } from 'react';
    import ResizeableView from './ResizeableView';
    import useData from '../hooks/useData';
    
    const numColumns = 2;
    const gap = 10;
    
    export default function AssetExample() {
      const [surveyData] = useData();
      const [flatlistHeight, setFlatlistHeight] = useState(0);
      return (
        <SafeAreaView style={{ flex: 1 }}>
          {/* draggable component to demonstrate responsiveness */}
          <ResizeableView />
          <FlatList
            style={{ flex: 1 }}
            data={surveyData?.surveys}
            contentContainerStyle={styles.cardsContainer}
            renderItem={({ item: surveyDetails, index: i }) => {
              const height = flatlistHeight / (6 / numColumns) - gap
              return (
                <Card
                  mode="elevated"
                  style={[
                    styles.cards,
                    { height },
                  ]}>
                  <Card.Content>
                    <Card.Title
                      title={surveyDetails.name}
                      titleVariant="titleLarge"
                      subtitle={surveyDetails.summary}
                      subtitleNumberOfLines={2}
                    />
                    <Image
                      source={{ uri: surveyDetails.thumbnail }}
                      style={{ width: height*.5,height:height*.5, alignSelf:'center' }}
                    />
                  </Card.Content>
                </Card>
              );
            }}
            keyExtractor={(item, i) => `suvey-card-${i}`}
            onLayout={({ nativeEvent }) =>
              setFlatlistHeight(nativeEvent.layout.height)
            }
            numColumns={numColumns}
            columnWrapperStyle={{ justifyContent: 'space-evenly' }}
            pagingEnabled
          />
        </SafeAreaView>
      );
    }
    
    const styles = StyleSheet.create({
      cardsContainer: {
        flexGrow: 1,
        padding: 5,
        gap,
      },
      cards: {
        backgroundColor: '#FFFFFF',
        borderRadius: 10,
        flexBasis: '45%',
        justifyContent: 'center',
        // borderWidth: 1,
      },
    });
    

    demo

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search