[英]React native grid like instagram
How can we achieve the grid like this .我们如何才能做到像电网这样。 I looked in many react native libraries but still in search of it.我查看了许多 react native 库,但仍在寻找它。 I tried a custom grid view but creating an issue when not having more data.我尝试了自定义网格视图,但在没有更多数据时创建了一个问题。 Please let me know the best way for it.请让我知道最好的方法。
I managed to do it for my project By creating a custom component.通过创建自定义组件,我设法为我的项目做到了这一点。
Note: Before you use the following component keep in mind that:注意:在使用以下组件之前,请记住:
ScrollView
instead of FlatList
because it wasn't feasible in my case.我使用ScrollView
而不是FlatList
因为在我的情况下它不可行。 And it might not be that efficient.它可能没有那么高效。lodash
Please make sure to install that.我使用了外部库lodash
请确保安装它。MyImage
which handles loading and errors according to my need.我有一个名为MyImage
的自定义子组件,它根据我的需要处理加载和错误。 You can skip and use your Image tag or Any Other.您可以跳过并使用您的图像标签或任何其他标签。Explanation:解释:
I created cells containing three images.我创建了包含三个图像的单元格。 There are a total of 3 types of cells.共有 3 种类型的细胞。
I create chunks or we can array of arrays using lodash
which works as data for each row.我创建块,或者我们可以使用lodash
来创建数组数组,它用作每一行的数据。 Each small chunk or array will have 3 objects.每个小块或数组将有 3 个对象。
groupEveryNthRow = 3
means I'll have cell with a big image on every 3rd row starting from 0. groupEveryNthRow = 3
表示从 0 开始,每第三行都有一个带有大图像的单元格。
bigImageSide
represents that on which side the big image should appear. bigImageSide
表示大图像应该出现在哪一侧。 I keep changing left to right.我不断地从左到右改变。 You can choose according to your case.您可以根据您的情况进行选择。
All other code is just self-explanatory.所有其他代码都是不言自明的。 Let me know if you don't understand anything else.如果您不了解其他任何内容,请告诉我。
Code代码
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;
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;
How to Use: Just使用方法:只需
<InstaGrid data={details} columns={3} loading={loading} onItemClick={(item) => { console.log('Got the Item:' + JSON.stringify(item)); }} onEndReachedThreshold={400} onEndReached={() => (offset !== -1 ? fetchData() : null)} />
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.