反应本机平面列表如何强制列表项具有相同的高度?

时间:2020-06-01 14:58:14

标签: react-native react-native-flatlist

我有一个React-Native应用程序,我在其中使用FlatList来显示从服务器获得的项目列表。列表有2列,我需要我的列表项高度相同。我在呈现列表项的代码周围放置了边框,但列表项的高度不同。我尝试使用flexbox设置使视图填充容器,但是我尝试的一切都没有区别。

我已经创建了我的应用程序的简化版本来说明问题:

enter image description here

请注意,红色边框区域的高度不同。我需要使它们的高度相同。

在包装负责列表项的组件的视图中添加了灰色边框,红色边框是负责列表项的组件的根视图。为清楚起见,请参见下面的代码。

我无法在应用程序中使用灰色边框,因为我的应用程序显示空白框,而负责列表项的组件在呈现自身之前已从服务器获取其他信息

enter image description here

此外,我不能使用固定尺寸的高度。

应用程序项目的结构和代码

我的代码以以下方式拆分:以“ container.js”结尾的文件从服务器获取数据,并将其传递到其匹配的呈现组件。例如,“ MainListContainer”将从服务器获取列表,然后将列表数据传递给“ MainList”,而“ ListItemContainer”将从服务器获取有关单个列表项的其他信息,并将其传递给“ ListItem”进行渲染实际项目。我已将此模型保留在简化的应用程序中,因此它尽可能接近我的实际应用程序。

enter image description here

index.js

import {AppRegistry} from 'react-native';
import MainListContainer from './app/components/MainListContainer';
import {name as appName} from './app.json';

AppRegistry.registerComponent(appName, () => MainListContainer);

MainListContainer.js

import React from 'react';
import MainList from './MainList';

const data = [
  {id: '1', title: 'Item 1', subtitle: 'A', description: 'This is the first item.'},
  {id: '2', title: 'Item 2', subtitle: 'B', description: 'The Big Brown Fox Jumped over the lazy dogs. The Big Brown Fox Jumped over the lazy dogs.',},
];

const MainListContainer = () => {
  return ( <MainList items={data} /> );
};

export default MainListContainer;

MainList.js

import React from 'react';
import {StyleSheet, FlatList, View} from 'react-native';
import ListItemContainer from './ListItemContainer';

export default class MainList extends React.Component {
  constructor(props) {
    super(props);
    this.state = { numColumns: 2};
    this.renderItem = this.renderItem.bind(this);
  }

  renderItem({item, index}) {
    return (
      <View style={styles.flatListItemContainer}>  <!-- THIS IS WHERE THE GREY BORDER IS ADDED -->
        <ListItemContainer key={index} item={item} />
      </View>
    );
  }

  render() {
    const {items} = this.props;
    const {numColumns} = this.state;

    return (
      <View>
        <FlatList
          data={items}
          renderItem={this.renderItem}
          numColumns={numColumns}
          key={numColumns}
          keyExtractor={(item) => item.id}
        />
      </View>
    );
  }
};


const styles = StyleSheet.create({

  flatListItemContainer: {
    flex: 1,
    margin: 10,

    borderColor: '#ccc',
    borderWidth: 1,
  },

});

ListItemContainer.js

import React from 'react';
import ListItem from './ListItem';

const ListItemContainer = (props) => {
    const { item } = props;

    return (
        <ListItem item={item} />
    );
};

export default ListItemContainer;

ListItem.js

import React from 'react';
import {TouchableHighlight, View, StyleSheet, Image, Text} from 'react-native';

const ListItem = (props) => {
  const { item } = props;

  return (
    <TouchableHighlight
      underlayColor="white"
    >
      <View style={styles.containerView}> <!-- THIS IS WHERE THE RED BORDER IS ADDED -->

        <View style={styles.top_row}>
          <Image style={styles.image} source={require('../images/placeholder.png')} />
          <View style={styles.title_texts}>
            <Text style={{fontWeight:'bold'}}>{item.title}</Text>
            <Text style={{color: 'rgb(115, 115, 115)'}}>{item.subtitle}</Text>
          </View>
        </View>

        <Text>{item.description}</Text>

      </View>
    </TouchableHighlight>
  );
};

export default ListItem;

const styles = StyleSheet.create({
  containerView: {
    padding: 14,

    borderColor: 'red',
    borderWidth: 1,
  },

  top_row: {
    flex: 1,
    flexDirection: 'row',
    marginBottom: 10,
  },

  title_texts: {
    flex: 1,
    flexDirection: 'column',
  },

  image: {
    alignSelf: 'flex-end',
    resizeMode: 'cover',
    height: 40,
    width: 40,
    marginRight: 20
  },

});

我尝试过的事情

  • ListItem.js:将样式移动到“ TouchableHighlight”视图上
  • ListItem.js:添加一个包装“ TouchableHighlight”视图的视图并在其中添加样式
  • ListItem.js:在“ TouchableHighlight”上添加了“ alignItems:'stretch”,将其添加到了“ containerView”样式中,并且也在说明字段中进行了尝试
  • 与“ alignItems”相同,但改用“ alignedSelf”
  • 与“ alignItems”相同,但改用“ alignedContent”
  • 在不同的视图(容器,说明)上尝试使用“ flexGrow”

2 个答案:

答案 0 :(得分:0)

您可以测量列表中每个元素的高度,当确定最大高度时,可以将该高度用于列表中的每个元素。

const Parent = ({ ...props }) => {
    const [maxHeight, setMaxHeight] = useState<number>(0);
    
    const computeMaxHeight = (h: number) => {
        if (h > maxHeight) setMaxHeight(h);
    }
    return (
        <FlatList
            data={props.data}
            renderItem={({ item }) => (
                <RenderItem 
                    item={item}
                    computeHeight={(h) => computeMaxHeight(h)}
                    height={maxHeight}
                />
            )}
            ....
        />
    )
}

项目:

const RenderItem = ({...props }) => {
    return (
        <View
            style={{ height: props.height }}
            onLayout={(event) => props.computeHeight(event.nativeEvent.layout.height)}
        >
          <Stuffs />
        </View>
    )
}

这是实现此目的的非常无效的方法。如果我的清单很长,或者有几个以上的清单,我会避免这种情况。但是,您可以进行某些检查以限制重新渲染等。或者,如果仅文本会影响高度,则只能测量包含最多文本的元素的高度,而其余部分则使用该元素的高度。 / p>

答案 1 :(得分:-1)

您错过了一个非常基本的概念,即为固定清单项目赋予固定高度,请在您的ListItem.js中尝试在height:200中设置containerView。让我知道这是否对您有用

相关问题