簡體   English   中英

像instagram一樣反應原生網格

[英]React native grid like instagram

我們如何才能做到像電網這樣 我查看了許多 react native 庫,但仍在尋找它。 我嘗試了自定義網格視圖,但在沒有更多數據時創建了一個問題。 請讓我知道最好的方法。

通過創建自定義組件,我設法為我的項目做到了這一點。

注意:在使用以下組件之前,請記住:

  1. 我使用ScrollView而不是FlatList因為在我的情況下它不可行。 它可能沒有那么高效。
  2. 我使用了外部庫lodash請確保安裝它。
  3. 這僅適用於 3 列圖像,但您可以根據需要進行更改。
  4. 我有一個名為MyImage的自定義子組件,它根據我的需要處理加載和錯誤。 您可以跳過並使用您的圖像標簽或任何其他標簽。

解釋:

我創建了包含三個圖像的單元格。 共有 3 種類型的細胞。

  1. 右側大圖。
  2. 左側大圖。
  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;

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;

使用方法:只需

 <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