【问题标题】:React Native number of components in one rowReact Native 一行中的组件数
【发布时间】:2019-12-05 18:25:20
【问题描述】:

我把它当作一种锻炼。有 28 个组件。我想要最多 4 行组件,其中每行最多有 7 个组件,最少 1 个,具体取决于屏幕尺寸(然后是 28 行)。你能帮我完成这个吗?我知道我可以使用 flex-wrap: wrap 样式,但我希望连续最多有 7 个组件。请帮我解决这个问题,因为我是 React Native 和 Flexbox 的新手。

    <View style={styles.container}>
      <View style={{ flex: 1, margin: 2, height: 40, backgroundColor: 'red'}}></View>
      <View style={{ flex: 1, margin: 2, height: 40, backgroundColor: 'green'}}></View>
      <View style={{ flex: 1, margin: 2, height: 40, backgroundColor: 'yellow'}}></View>
      <View style={{ flex: 1, margin: 2, height: 40, backgroundColor: 'brown'}}></View>
      <View style={{ flex: 1, margin: 2, height: 40, backgroundColor: 'blue'}}></View>
      <View style={{ flex: 1, margin: 2, height: 40, backgroundColor: 'red'}}></View>
      <View style={{ flex: 1, margin: 2, height: 40, backgroundColor: 'green'}}></View>
.
.
.
    </View>

const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: 'row',
    justifyContent: 'center',
  },
});

【问题讨论】:

  • minWidth: `${100/7}%` 怎么样?

标签: reactjs react-native flexbox


【解决方案1】:

这个问题无法通过引导方式解决(列、行等)。 Flexbox 缺乏使特定数量的组件根据屏幕大小连续显示的能力。

您需要使用 ListView 以便 ListView 连续呈现 7 个组件。 ListView 的 renderRow 函数遍历一个数组,并在一行中显示该数组的每个索引的内容。所以,在每个索引处你需要定义包含7个属性的json,并以数组的形式返回所有这些属性,使它们出现在一行中。

在我的项目中,我必须连续显示 3 张或更少的图像(如附加图像的媒体部分所示),因此我使用上述方法来实现这一点。请在下面找到我的代码。这可能会对您有所帮助。

constructor() {
  // data saved in state
  this.state = {
    mediaFiles: [{image: "image link"}, 
                 {image: "image link"},
                 {image: "image link"},
                 {image: "image link"},
                 {image: "image link"},
                 {image: "image link"},
                 {image: "image link"},
                 {image: "image link"},
                ],
    dataSource: ds.cloneWithRows([])
  }
}

componentDidMount() {
  var temp = [];

  //to ensure three images appear in a row
  for (var index     = 0; index < this.state.mediaFiles.length; index = index + 3) {
      temp.push({
        image1: this.state.mediaFiles[index].image,
        image2: (index + 1) < this.state.mediaFiles.length ? this.state.mediaFiles[index + 1].image : null,
        image3: (index + 2) < this.state.mediaFiles.length ? this.state.mediaFiles[index + 2].image : null
      });
  }

  this.setState({
      dataSource: this.state.dataSource
       .cloneWithRows(temp)
  });
}

renderMediaThumbnails(rowData) {
  var mediaThumbnails = [],
    key = 0;

  for (var attribute in rowData) {
    if (rowData[attribute]) {
      mediaThumbnails.push(
        <View key={key++} style={Styles.imageWrapper}>
        <Image style={Styles.media} source={{uri: rowData[attribute]}} />
        </View>)
    }
  }
  return mediaThumbnails
}

renderRow(rowData) {
  return (
    <View style={Styles.mediaWrapper}>
      {this.renderMediaThumbnails(rowData)}
    </View>
  );
}

render() {
  return (
    <View style={Styles.statusAndMedia}>
      <ListView
        dataSource={this.state.dataSource}
        renderRow={this.renderRow.bind(this)} />
    </View>
  );
}

以下是样式:

mediaWrapper: {
  flex: 1,
  flexDirection: "row",
  justifyContent: "space-around",

  marginVertical: 3,
},

imageWrapper: {
  borderWidth: 2,
  borderColor: "#AE8B8C"
},

media: {
  height: 50,
  width: 85,

  resizeMode: "stretch"
}

【讨论】:

  • 感谢 Mohammad,但我认为我的情况有点不同。在给定 28 个元素的情况下,我希望最多连续 7 个元素(即使屏幕尺寸可以连续容纳更多元素)。如果屏幕很小,我每行的元素会更少(当然最少是 1)。 flex-wrap 工作正常,但我不知道有什么方法可以告诉它在 7 处停止(或者更确切地说,在宽度上,这将是这 7 个元素的宽度)。
  • 在您的情况下,当屏幕的宽度小于连续所有 3 张图片的宽度时会发生什么?
  • 是的,没错。我的解决方案可能会解决您的第一个问题(最多连续 7 个),但即使屏幕尺寸变短,它也不会做不同的事情。在我的例子中,我给图片设置了固定的宽度,较短的屏幕尺寸只会减少图片之间的差距。
  • 我只是确保连续出现的元素不超过三个。如果要在不同的屏幕尺寸上连续显示不同数量的项目,则需要使用 Dimension 类并在运行时获取屏幕宽度,然后在元素上设置样式。这种行为不能单独使用 flex-box 实现
【解决方案2】:

好的,我想我找到了解决方案。如果屏幕尺寸较大,我将父视图的宽度设置为屏幕或 294(7 个元素的宽度 + 边距)。也许将其硬编码为 294 就足够了,但我现在无法在小屏幕上查看它。

var width = Dimensions.get('window').width;

class Schedule extends React.Component {

  render() {
    return (
        <View style={styles.container}>
          <View style={{ margin: 1, width: 40, height: 40, backgroundColor: 'red'}}></View>
          <View style={{ margin: 1, width: 40, height: 40, backgroundColor: 'green'}}></View>
          <View style={{ margin: 1, width: 40, height: 40, backgroundColor: 'yellow'}}></View>
          <View style={{ margin: 1, width: 40, height: 40, backgroundColor: 'brown'}}></View>
          <View style={{ margin: 1, width: 40, height: 40, backgroundColor: 'blue'}}></View>
          <View style={{ margin: 1, width: 40, height: 40, backgroundColor: 'red'}}></View>
          <View style={{ margin: 1, width: 40, height: 40, backgroundColor: 'green'}}></View>
          <View style={{ margin: 1, width: 40, height: 40, backgroundColor: 'red'}}></View>
        </View>
    )
  }
};


export default Schedule;

const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: 'row',
    flexWrap: 'wrap',
    width: width > 294 ? 294 : width
  },
});

【讨论】:

    【解决方案3】:

    ListView 现已弃用,您可以使用 SectionList 或 FlatList 代替。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-02-02
      • 2016-11-18
      • 2020-05-06
      • 2020-04-13
      • 1970-01-01
      • 2023-03-29
      • 1970-01-01
      相关资源
      最近更新 更多