Search code examples
cssreact-nativepositioncontainerscss-position

ReactNative:Styles overriding each other and container goes out of position


  render() {
    if (this.state.isLoading) {
      return (
        <View style={styles.container}>
          <ActivityIndicator />
        </View>
      );
    } else {
      let launches = this.state.dataSource.map((item, key) => {
        return (
          <View key={key} style={styles.container}>
            <Image
              style={{ width: 350, height: 520, borderRadius: 10 }}
              source={{ uri: item.rocket.imageURL }}
            />
            <Entypo
              name="map"
              color={"white"}
              size={24}
              style={styles.MapIcon}
              onPress={() => Linking.openURL(item.location.pads[0].mapURL)}
            />
            <Entypo
              name="video-camera"
              color={"white"}
              size={24}
              style={styles.VideoIcon}
              onPress={() => Linking.openURL(item.vidURLs[0])}
            />

            <View style={styles.subcontainer}>
              <Text style={styles.Title}>{item.missions[0].name}</Text>
              <Text>
                <Text style={styles.TextHeader}>Location: </Text>
                <Text style={styles.Text}>{item.location.name}</Text>
              </Text>
              <Text>
                <Text style={styles.TextHeader}>Launch Date: </Text>
                <Text style={styles.Text}>{item.net}</Text>
              </Text>
              <Text>
                <Text style={styles.TextHeader}>Service Provider: </Text>
                <Text style={styles.Text}>{item.lsp.name}</Text>
              </Text>
              <Text>
                <Text style={styles.TextHeader}>Rocket: </Text>
                <Text style={styles.Text}>{item.rocket.name}</Text>
              </Text>
            </View>
          </View>
        );
      });

      return (
        <View style={styles.Background}>
          <ScrollView contentContainerStyle={styles.contentContainer}>
            {launches}
          </ScrollView>
        </View>
      );
    }
  }
}

const styles = StyleSheet.create({
  Background: {
    backgroundColor: "#e8e8e8"
  },
  contentContainer: {
    padding: 3,
    backgroundColor: "#e8e8e8"
  },
  subcontainer: {
    backgroundColor: "rgb(249, 249, 249)",
    position: "absolute",
    borderRadius: 2,
    padding: 10,
    marginTop: 420,
    width: "100.65%",
    marginLeft: "2.94%",
    shadowColor: "grey",
    shadowOpacity: 0.5,
    shadowRadius: 2,
    shadowOffset: { width: 0, height: -1 }
  },
  container: {
    flex: 1,
    borderRadius: 10,
    backgroundColor: "rgba(249, 249, 249, 0.8)",
    padding: 10,
    borderWidth: 0.5,
    borderColor: "#CCCCCC",
    marginTop: 4
  },
  Title: {
    color: "#007AFF",
    fontSize: 18,
    textAlign: "center",
    lineHeight: 18,
    paddingBottom: 5,
    fontWeight: "bold"
  },
  Text: {
    color: "black",
    fontSize: 14,
    textAlign: "left"
  },
  TextHeader: {
    color: "#007AFF",
    fontSize: 14,
    textAlign: "left",
    fontWeight: "bold"
  },
  MapIcon: {
    position: "absolute",
    marginTop: "7%",
    marginLeft: "8%"
  },
  VideoIcon: {
    position: "absolute",
    marginTop: "7%",
    marginLeft: "92%"
  }
});

The pictures below show a better representation, but to thoroughly explain it, I have a container and in it has a sub-container with information about the name of the launch, location, date, rocket etc. and the sub-container should fit nicely into each container/card ( card being for each rocket launch event, it gets its own container with padding etc.) but sometimes some of the text becomes too long and has to take up another row. This forces the sub-container to move down (displayed in "how it shouldn't be" image and extend out from the container/card. Q: is there a way such that whenever the text requires another row that the sub-container moves upward along with the text in it so it still fits in the container/card and doesn't go extending outside of it? or another solution.

How it shouldn't be

How it should be


Solution

  • One way to solve this problem is to absolute position your subContainer to the bottom of the Container using bottom:0, instead of providing marginTop:420. This way the subContainer View will always stick to the bottom of the Container View. Whereas providing marginTop:420 will make the subContainer View always have marginTop of 420 which will push it down when it becomes big. You can also play with left: 0 and right: 0 for the subContainer to occupy the full width of its parent View, i.e the Container.

    class App extends React.Component {
      render() {
        return (
          <ScrollView style={{marginTop: 25}} >
            {[1,2,3,4,5].map(() => (
              <View style={styles.container}>
                <View style={styles.subContainer} >
                  <Text>on every element in the calling array on every element in the calling array on every element in the calling array</Text>
                </View>
              </View>
            ))}
          </ScrollView>
        );
      }
    }
    
    const styles = StyleSheet.create({
      container: {
        backgroundColor: 'blue',
        height: 300,
        margin: 10
      },
      subContainer: {
        backgroundColor: '#eee',
        position: 'absolute',
        bottom: 0,
        right: 0,
        left: 0,
        margin: 10,
        padding: 5,
        borderRadius: 2
      },
    });
    

    Check out the working example: https://snack.expo.io/SyXDLkEDX

    Check and tell if it helps.