cak*_*PHP 2 css gridview react-native
怎样才能实现这样的网格呢?我查看了许多 React Native 库,但仍在寻找它。我尝试了自定义网格视图,但在没有更多数据时产生了问题。请让我知道最好的方法。
我设法通过创建自定义组件为我的项目做到这一点。
注意:在使用以下组件之前,请记住:
ScrollView代替,FlatList因为它在我的情况下不可行。而且效率可能没那么高。lodash请确保安装它。MyImage,它根据我的需要处理加载和错误。您可以跳过并使用您的图像标签或任何其他标签。解释:
我创建了包含三个图像的单元格。共有3种类型的细胞。
我创建块,或者我们可以使用数组数组lodash作为每行的数据。每个小块或数组将有 3 个对象。
groupEveryNthRow = 3意味着我将从 0 开始的每第三行都有一个带有大图像的单元格。
bigImageSide表示大图像应该出现在哪一侧。我不断地从左到右改变。您可以根据您的情况进行选择。
所有其他代码都是不言自明的。如果您不明白其他任何内容,请告诉我。
代码
InstaGrid.js
import React from 'react';
import {
View,
StyleSheet,
Dimensions,
ScrollView,
ActivityIndicator,
} from 'react-native';
var {width} = Dimensions.get('window');
import * as _ from 'lodash';
import MyImage from './MyImage';
const InstaGrid = ({
data,
columns,
onEndReachedThreshold,
onEndReached,
loading = false,
onItemClick,
}) => {
const groupEveryNthRow = 3;
const {mainContainer, groupedGridContainer} = styles;
var currentRow = 0;
const rowsArray = _.chunk(data, columns);
var bigImageSide = 'right';
const renderGroupedItem = (row) => {
const smallImage1 = row[0];
const smallImage2 = row[1];
const largeImage = row[2];
if (bigImageSide === 'right') {
bigImageSide = 'left';
return (
<View style={{flexDirection: 'row'}}>
<View style={groupedGridContainer}>
<View style={styles.gridStyle}>
<MyImage
style={styles.imageThumbnail}
sourceObj={smallImage1}
onPress={() => {
onItemClick(smallImage1);
}}
/>
</View>
<View style={styles.gridStyle}>
<MyImage
style={styles.imageThumbnail}
sourceObj={smallImage2}
onPress={() => {
onItemClick(smallImage2);
}}
/>
</View>
</View>
<View style={styles.gridStyle}>
<MyImage
style={styles.imageThumbnailLarge}
sourceObj={largeImage}
onPress={() => {
onItemClick(largeImage);
}}
/>
</View>
</View>
);
} else {
bigImageSide = 'right';
return (
<View style={{flexDirection: 'row'}}>
<View style={styles.gridStyle}>
<MyImage
style={styles.imageThumbnailLarge}
sourceObj={largeImage}
onPress={() => {
onItemClick(largeImage);
}}
/>
</View>
<View style={groupedGridContainer}>
<View style={styles.gridStyle}>
<MyImage
style={styles.imageThumbnail}
sourceObj={smallImage1}
onPress={() => {
onItemClick(smallImage1);
}}
/>
</View>
<View style={styles.gridStyle}>
<MyImage
style={styles.imageThumbnail}
sourceObj={smallImage2}
onPress={() => {
onItemClick(smallImage2);
}}
/>
</View>
</View>
</View>
);
}
};
const renderSingleItem = (item) => {
return (
<View style={styles.gridStyle}>
<MyImage
style={styles.imageThumbnail}
sourceObj={item}
onPress={() => {
onItemClick(item);
}}
/>
</View>
);
};
const renderCell = (row) => {
if (row.length >= columns && currentRow % groupEveryNthRow === 0) {
currentRow++;
return <View>{renderGroupedItem(row)}</View>;
}
currentRow++;
return (
<View style={{flexDirection: 'row'}}>
{row.map((item) => {
return renderSingleItem(item);
})}
</View>
);
};
const isCloseToBottom = ({layoutMeasurement, contentOffset, contentSize}) => {
const paddingToBottom = 20;
return (
layoutMeasurement.height + contentOffset.y >=
contentSize.height - paddingToBottom
);
};
const renderFooter = () => {
return (
<View style={{marginBottom: 16}}>
<ActivityIndicator animating size="large" />
</View>
);
};
return (
<ScrollView
scrollEventThrottle={onEndReachedThreshold}
onScroll={({nativeEvent}) => {
if (isCloseToBottom(nativeEvent)) {
onEndReached();
}
}}>
<View style={mainContainer}>
{rowsArray.map((row) => {
return renderCell(row);
})}
</View>
{loading && renderFooter()}
</ScrollView>
);
};
const styles = StyleSheet.create({
mainContainer: {
width: '100%',
},
groupedGridContainer: {
flexDirection: 'column',
flexWrap: 'wrap',
},
imageThumbnail: {
height: width / 3 - 12,
width: width / 3 - 12,
resizeMode: 'stretch',
alignSelf: 'flex-start',
justifyContent: 'flex-start',
},
imageThumbnailLarge: {
height: width * 0.6 + 12,
width: width * 0.6 + 12,
marginLeft: 4,
resizeMode: 'stretch',
alignSelf: 'flex-start',
justifyContent: 'flex-start',
},
gridStyle: {
margin: 4,
},
});
export default InstaGrid;Run Code Online (Sandbox Code Playgroud)
MyImage.js
import React, {useState} from 'react';
import {
TouchableOpacity,
Image,
StyleSheet,
ActivityIndicator,
} from 'react-native';
const MyImage = ({style, sourceObj, onPress}) => {
const [imageError, setImageError] = useState(false);
const [loading, setLoading] = useState(true);
return (
<TouchableOpacity onPress={onPress}>
{imageError || !sourceObj.card_images ? (
<Image
source={require('../images/userImage.jpg')}
style={style}
onLoadEnd={() => setLoading(false)}
/>
) : (
<Image
style={style}
source={{uri: sourceObj.card_images.front_image}}
onError={(e) => {
setLoading(false);
setImageError(true);
}}
onLoadEnd={() => setLoading(false)}
/>
)}
{loading && (
<ActivityIndicator
style={styles.activityIndicator}
animating={loading}
/>
)}
</TouchableOpacity>
);
};
const styles = StyleSheet.create({
activityIndicator: {
position: 'absolute',
left: 0,
right: 0,
top: 0,
bottom: 0,
},
});
export default MyImage;Run Code Online (Sandbox Code Playgroud)
使用方法:只需
<InstaGrid
data={details}
columns={3}
loading={loading}
onItemClick={(item) => {
console.log('Got the Item:' + JSON.stringify(item));
}}
onEndReachedThreshold={400}
onEndReached={() => (offset !== -1 ? fetchData() : null)}
/>Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2490 次 |
| 最近记录: |