4

我正在使用平面列表来创建包含图像、视频、博客和音频的项目网格。平面列表中有两列。我添加了一个按钮来在平面列表中添加虚拟帖子。问题是物品的高度。当我在 flatlist 中添加博客时,其中包含文本、图像和旁边的项目。即图像或视频也获取博客项目的高度。是否可以为行中的每个项目赋予可变高度。在将博客添加到平面列表视频项目时,其高度也与博客项目相同。

问题截图

4

4 回答 4

4

根据官方文件,当平面列表有多个列时,Items should all be the same height - masonry layouts are not supported.

但我认为您可以尝试View在每个列项上添加一个包装器来避免此规则。flatlistheight将在包装器上设置,您的项目高度仍然可以由您配置。

于 2017-08-23T15:12:48.900 回答
3

我使用这个库来创建一个砌体列表。 https://github.com/AppAndFlow/react-native-masonry-list。它按预期工作。

于 2018-03-19T07:26:12.480 回答
0

您可以尝试在具有一个元素的 FlatList 中使用 ScrollView。

import React, {useEffect, useState} from 'react';
import {
  View,
  FlatList,
  Image,
  ScrollView,
  Text,
  Dimensions,
} from 'react-native';
const {height, width} = Dimensions.get('window');
const DATA = [
  {
    url:
      'https://images.pexels.com/photos/4689912/pexels-photo-4689912.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500',
    height: 400,
  },
  {
    url:
      'https://images.pexels.com/photos/2736843/pexels-photo-2736843.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500',
    height: 100,
  },
  {
    url:
      'https://images.pexels.com/photos/4407291/pexels-photo-4407291.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500',
    height: 100,
  },
  {
    url:
      'https://images.pexels.com/photos/4553021/pexels-photo-4553021.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500',
    height: 200,
  },
  {
    url:
      'https://images.pexels.com/photos/4689912/pexels-photo-4689912.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500',
    height: 200,
  },
  {
    url:
      'https://images.pexels.com/photos/2736843/pexels-photo-2736843.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500',
    height: 200,
  },
  {
    url:
      'https://images.pexels.com/photos/4407291/pexels-photo-4407291.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500',
    height: 200,
  },
  {
    url:
      'https://images.pexels.com/photos/4553021/pexels-photo-4553021.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500',
    height: 200,
  },
  {
    url:
      'https://images.pexels.com/photos/4689912/pexels-photo-4689912.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500',
    height: 200,
  },
  {
    url:
      'https://images.pexels.com/photos/2736843/pexels-photo-2736843.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500',
    height: 200,
  },
  {
    url:
      'https://images.pexels.com/photos/4407291/pexels-photo-4407291.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500',
    height: 200,
  },
  {
    url:
      'https://images.pexels.com/photos/4553021/pexels-photo-4553021.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500',
    height: 200,
  },
  {
    url:
      'https://images.pexels.com/photos/4689912/pexels-photo-4689912.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500',
    height: 200,
  },
  {
    url:
      'https://images.pexels.com/photos/2736843/pexels-photo-2736843.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500',
    height: 200,
  },
  {
    url:
      'https://images.pexels.com/photos/4407291/pexels-photo-4407291.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500',
    height: 200,
  },
  {
    url:
      'https://images.pexels.com/photos/4553021/pexels-photo-4553021.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500',
    height: 200,
  },
];
const W = width / 2 - 10 - 4;
const Item = ({url, height}) => {
  const [dims, setDims] = useState({height: 0, width: 0});
  useEffect(() => {
    setDims({height: Math.random() * 1000});
    // Image.getSize(url, ([h, w]) => {
    //   console.log('<<h, w', h, w);
    // });
  }, [url]);
  return (
    <View
      style={{
        width: W,
        height: dims.height,
        margin: 5,
        padding: 1,
        backgroundColor: 'red',
      }}>
      {/* <Text>{JSON.stringify(dims, null, 2)}</Text> */}
      <Image
        source={{uri: url}}
        style={{
          height: '100%',
          width: '100%',
        }}
      />
    </View>
  );
};
export default () => {
  const [data, setData] = useState([...DATA]);
  // let prevY = React.useRef(0).current;
  // const offsetY = new Animated.Value(0);
  return (
    <View
      style={{
        flex: 1,
        backgroundColor: '#DDDDDD',
        flexDirection: 'row',
      }}>
      <FlatList
        data={[1]}
        onEndReached={() => {
          setData((prev) => {
            return [...prev, ...DATA];
          });
          console.log('<<EENDDD');
        }}
        renderItem={() => {
          return (
            <ScrollView
              contentContainerStyle={{
                flexDirection: 'row',
                backgroundColor: 'blue',
                marginVertical: 10,
              }}>
              <View>
                {data.map((item) => {
                  return <Item {...item} />;
                })}
              </View>
              <View>
                {data.map((item) => {
                  return <Item {...item} />;
                })}
              </View>
            </ScrollView>
          );
        }}
      />
    </View>
  );
};
于 2020-10-12T09:07:04.147 回答
-1

有趣的是,这可以在没有任何外部库的情况下实现。诀窍是使用负边距。

实现有点棘手 - 我们需要在 VirtualizedList 属性 CellRendererComponent 中应用负边距,以使其在 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'
   }
});

确保正确排列数组中图像的数据 - 始终将较高的图像放在较短的一侧,计算高度差等。

于 2019-03-15T23:19:27.577 回答