简体   繁体   English

像instagram一样反应原生网格

[英]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:注意:在使用以下组件之前,请记住:

  1. I have used ScrollView instead of FlatList because it wasn't feasible in my case.我使用ScrollView而不是FlatList因为在我的情况下它不可行。 And it might not be that efficient.它可能没有那么高效。
  2. I have used external library lodash Please make sure to install that.我使用了外部库lodash请确保安装它。
  3. This is only working with 3 Column images but you can make changes according to your need.这仅适用于 3 列图像,但您可以根据需要进行更改。
  4. I have a custom sub-component called 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 种类型的细胞。

  1. Big Image on the right side.右侧大图。
  2. Big Image on the left side.左侧大图。
  3. Normal grid with No Big Image.没有大图像的普通网格。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM