React Native - 具有动态高度子级的 FlatList [英] React Native - FlatList with dynamic height children

查看:67
本文介绍了React Native - 具有动态高度子级的 FlatList的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在努力将砖石风格的风格融入到我的应用中.我尝试应用 react-native-masonry 包.但是,您必须传递图像 url.我试图完成相同的风格,但渲染文本而不一定渲染图像.

I´ve been struggling to get the masonry-like style into my app. I tried applying the react-native-masonry package. However you must pass an image url. I am trying to accomplish the same style but to render text without necessarily rendering an image.

到目前为止,我一直在围绕 FlatList 工作,但这是我所能做到的.

So far I´ve work my way around a FlatList, but this is as far as I could get.

 <FlatList
data={[
    { id: 1, username: "user1", title: "Title test", heigth: 150 },
    {
        id: 2,
        username: "RH",
        title: "Testing the length of a title with an image",
        image: "http://localhost:5005/dummy.png",
        heigth: 300
    },
    { id: 3, username: "john", title: "Another not so long title" },
    {
        username: "CAF",
        title:
            "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
        heigth: 600
    }
]}
keyExtractor={this._keyExtractor}
renderItem={this._renderItem}
numColumns={2}
/>;

我正在为卡片硬编码不同的长度,但它们似乎坚持行上的最大高度.

I am hardcoding different lengths to the cards but it seems that they stick to the largest height on the row.

这是我的卡片组件(renderItem).

And this is my card component (renderItem).

 _renderItem = ({ item }) => (
<Card style={{ height: item.heigth }}>
    <CardItem>
        <Left>
            <Text style={{ fontWeight: "bold", fontSize: 20 }}>
                {item.title}
            </Text>
        </Left>
    </CardItem>
    <CardItem cardBody style={{ marginBottom: 5 }}>
        {!isEmpty(item.image) && (
            <Image
                source={{ uri: item.image }}
                style={{ width: 170, flex: 1, height: 100 }}
            />
        )}
    </CardItem>
    <CardItem>
        <Left />
        <Body />
        <Right>
            <Text note>{item.username}</Text>
        </Right>
    </CardItem>
</Card>
);

谢谢

推荐答案

我找到了一种在 React Native 中实现这一目标的方法——不需要外部库.诀窍是使用负边距.实现有点棘手,但不是太难.

I found a way to achieve this in react native - no external libraries needed. The trick is to use negative margin. The implementation is slightly tricky, but not too difficult.

我们需要在 VirtualizedList 道具 CellRendererComponent 中应用负边距,以使其在 Android 上正常工作.

We need to apply the negative margin in the VirtualizedList prop CellRendererComponent in order to get it to work properly on Android.

JSX:

<View style={styles.container}>
      <FlatList
        style={styles.flatlist}
        data={data}
        keyExtractor={(item, index) => index.toString()}
        CellRendererComponent={({ children, item, ...props }) => {
            return (
                <View {...props} style={{ marginTop: item.marginTop }}>
                    {children}
                </View>
            )
        }}
        renderItem={({ item }) => {
            const { source: source1, height: height1, marginTop: marginTop1 } = item.image1;
            const { source: source2, height: height2, marginTop: marginTop2 } = item.image2;
            return (
                <View style={Style.viewRow}>
                    <Image source={source1} style={[styles.image, { height: height1, marginTop: marginTop1 }]} />
                    <Image source={source2} style={[styles.image, { height: height2, marginTop: marginTop2 }]} />
                </View>
            )
        }}
    />
</View>

数据:

const source = { uri: 'https://placekitten.com/160/300' };

const data = [
    {
        marginTop: 0,
        image1: { source, height: 300, marginTop: 0 },
        image2: { source, height: 250, marginTop: 0 }
    },
    {
        marginTop: -50,
        image1: { source, height: 290, marginTop: 50 },
        image2: { source, height: 300, marginTop: 0 }
    },
    {
        marginTop: -40,
        image1: { source, height: 250, marginTop: 40 },
        image2: { source, height: 350, marginTop: 0 }
    }
];

风格:

const styles = StyleSheet.create({
   container: {
      flex: 1
   },
   flatList: {
      width: '100%',
      height: '100%'
   },
   viewRow: {
      flexDirection: 'row'
   },
   image: {
      width: '50%',
      resizeMode: 'cover'
   }
});

剩下的唯一工作就是排列数组中的图像数据.确保有图像的高度,始终将较高的图像放在较短的一侧,然后计算差异......享受.

The only work that's left for you is to arrange the data of the images in the array. Make sure to have the height of the images, always place the taller image in the shorter side, and then calculate the difference... Enjoy.

这篇关于React Native - 具有动态高度子级的 FlatList的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆