Flexbox does not constraint itself to parent width and always overflows

475 Views Asked by At

I am struggling to understand why flexbox will not constraint itself to the parent component width. I have tried multiple approaches without much luck and my buttons are always overflowing the parent component.

Here is what I have so far: https://snack.expo.io/@mohammedri/smart-bagel enter image description here

and here is what I want instead (top 4 red boxes are buttons, next red box is a text field and the last one is the reset table button): enter image description here

I am using UI kitten for theming, but don't think it should impact the outcome. I have tried resizeMode as well, but it doesn't seem to work. Any help is appreciated.

I have posted majority of my code below:

App.js:

export default function App() {
  const Tab = createBottomTabNavigator();

  return (
    <ApplicationProvider {...eva} theme={eva.light}>
      <SafeAreaView style={styles.container}>
        <NavigationContainer>
            {/* ... More code */}
            <Tab.Screen name="Home" component={HomeScreen} />
            {/* ... More code */}
          </Tab.Navigator>
        </NavigationContainer>
      </SafeAreaView>
    </ApplicationProvider>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#fff",
  },
});

HomeScreen.js:

  return (
    <WaterIntakeContext.Provider value={{dayTotalWater, setDayTotalWater}}>
      <View style={styles.container}>
        <View style={styles.statusContainer}>
          <Text style={styles.titleText} category="h3">some text</Text>
          <Text style={styles.subtitleText} category="h6">some text</Text>
          <Text style={styles.statusTextWater} category="p1">some text</Text>
          <Text style={styles.statusTextWR} category="p1">You have gone to the washroom {numTimesDay} times today with each trip being an average of {avgTime} seconds long.</Text>
        <Divider></Divider>
        </View>
        <View style={styles.timerContainer}>
           <Timer setTimerStateChanged={setTimerStateChanged} />
        </View>
        <View style={styles.waterContainer}>
          <Divider></Divider>
          <WaterIntake />
        </View>
      </View>
    </WaterIntakeContext.Provider>
  );
};

const styles = StyleSheet.create({
    container: {
      flex: 1,
      flexDirection: "column",
      justifyContent: "flex-start",
      flexWrap: 'wrap',
      backgroundColor: "#fff",
      paddingRight: 30,
      paddingLeft: 30,
      paddingTop: 20
    },
    statusContainer: {
      borderLeftWidth: 1,
      borderRightWidth: 1,
      borderTopWidth: 1,
      borderBottomWidth: 1,
      flex: 1
    },
    waterContainer: {
      borderLeftWidth: 1,
      borderRightWidth: 1,
      borderTopWidth: 1,
      borderBottomWidth: 1,
      flex: 1,
      width: "100%",
    },
    timerContainer: {
      borderLeftWidth: 1,
      borderRightWidth: 1,
      borderTopWidth: 1,
      borderBottomWidth: 1,
      flex: 2,
      paddingBottom: 10,
    },
    titleText: {
      paddingBottom: 5
    },
    subtitleText: {
      paddingBottom: 20
    },
    statusTextWater: {
      paddingBottom: 10
    },
    statusTextWR: {
      paddingBottom: 20
    }
  });

and finally inside WaterIntake.jsx:

  return (
    <View style={styles.container}>
      <Text category="h6" style={{paddingTop: 20, paddingBottom: 15}}>Water log</Text>
      
      <View style={styles.buttonView}>
        <Button style={styles.button} onPress={async () => {
          await recordWaterIntake(0.25)
        }} >1/4 Cup</Button> 
        <Button style={styles.button} onPress={async () => {
          await recordWaterIntake(0.5)
        }}> 1/2 Cup </Button>
        <Button style={styles.button} onPress={async () => {
          await recordWaterIntake(0.75)
        }}> 3/4 Cup </Button>
        <Button style={styles.button} onPress={async () => {
          await recordWaterIntake(1)
        }}> 1 Cup </Button>
      </View>
      <View style={styles.containerText}>
        <Text>Total water consumed: {dayTotalWater}</Text>

        <Button onPress={resetWaterDb}>Reset table</Button>
      </View>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    backgroundColor: "#fff",
    justifyContent: "space-between"
  },
  buttonView: {
    flex: 1,
    flexDirection: "row",
    width: "100%",
    resizeMode: 'contain',
  },
  containerText: {
    flex: 2,
    flexDirection: 'column'
  },
  button: {
    margin: 2,
    // width:"22%",
    
  }
});
1

There are 1 best solutions below

3
Sam Phillemon On
  1. Wrapping the buttonView div in flex: wrap
    buttonView: {
    flex: 1,
    flexDirection: "row",
    width: "100%",
    resizeMode: 'contain',
    flexWrap: 'wrap'
  },
  1. You can make it as a scrollable:
  buttonView: {
    flex: 1,
    flexDirection: "row",
    width: "100%",
    resizeMode: 'contain',
    overflow: 'auto'
  },

Screenshot: enter image description here