React Native 使用 FlatList 實現九宮格布局
先看圖片演示實例:

本文以圖片列表為例,實現九宮格布局!
主要有兩種方法:
1)方法一:
利用FlatList的
numColumns ={2} // 一行2個
2)方法二:
利用 FlatList的
contentContainerStyle={styles.listViewStyle}
其中樣式如下:
listViewStyle: {
// 主軸方向
flexDirection: 'row',
// 一行顯示不下,換一行
flexWrap: 'wrap',
// 側軸方向
alignItems: 'center', // 必須設置,否則換行不起作用
},
當然,有一個重要的前提是,列表中的元素寬度 當然也要設置為寬度的 1/N,
看實際使用例子代碼:
import React, {Component} from 'react';
import {FlatList, ActivityIndicator, Image, RefreshControl, Text, TouchableHighlight, View} from 'react-native';
import Dimensions from 'Dimensions';
import styles from '../../style/ImageStyle';
import ArrUtil from '../../util/ArrUtil';
import HttpRequest from '../../common/HttpRequest';
const baseUrl = 'https://raw.githubusercontent.com/wukong1688/RN-AppNews/master/apk/data/image_list_';
const screenWidth = Dimensions.get('window').width;
let pageNo = 0;//當前第幾頁
let totalPage = 2;//總的頁數
/**
* 新聞主頁
*/
class ImagePage extends Component {
constructor(props) {
super(props);
//在這里定義json返回的key
this.state = {
//下拉刷新,上拉加載
isRefreshing: true, //下拉刷新標記
isLoading: false, //上拉加載標記
//data數據
resultJson: null,
error_code: '',
reason: '',
data: {},
//網絡請求狀態
error: false,
errorInfo: "",
showFoot: 0, // 控制foot, 0:隱藏footer 1:已加載完成,沒有更多數據 2 :顯示加載中
}
}
componentDidMount() {
pageNo = 0; //切換tab時 pageNo 也要歸零
this.fetchData(baseUrl + '0.json', 0); //默認從0頁數據開始讀
}
fetchData(url, pageNo) {
const opts = {
method: 'GET',
headers: HttpRequest.getHeaders(),
};
fetch(url, opts)
.then((res) => {
return res.json();
})
.then((response) => {
this.setData(response);
})
.catch((error) => {
alert(error);
// console.error(error);
})
.done();
}
setData(response){
let foot = 0;
if (pageNo >= totalPage) {
foot = 1;//listView底部顯示沒有更多數據了
}
let dataRes = [];
let responseData = ArrUtil.shuffle(response.results);
if (this.state.isRefreshing) { //刷新,以前的數據全部清掉
dataRes = responseData;
} else { //加載,數據追加到后面
dataRes = this.state.data.concat(responseData);
}
this.setState({
isRefreshing: false,
isLoading: false,
showFoot: foot,
data: dataRes,
});
}
//下拉刷新
_onRefresh(type) {
this.setState({
showFoot: 2,
isRefreshing: true
});
pageNo = 0; //刷新時,頁碼歸0
this.fetchData(baseUrl + type + '.json', type);
}
//列表點擊事件
itemClick(item, index) {
this.props.navigation.navigate('ImageDetail', {
title: item.desc,
url: item.url,
})
}
//FlatList的key
_keyExtractor = (item, index) => index.toString();
//子item渲染
_renderItem = ({item, index}) => {
let w = screenWidth * 0.5 - 7;
let h = screenWidth * 0.65 - 7;
let style = styles.itemPadding;
return (
<TouchableHighlight
key={item._id}
style={style}
underlayColor={'rgba(255,255,255,0.5)'}
onPress={this.itemClick.bind(this, item, index)}
>
<Image
defaultSource={require('../../res/image_icon.png')}
source={{uri: item.url}} style={{height: h, width: w}}
resizeMethod="resize"
/>
</TouchableHighlight>
)
};
//列表分割線
_itemDivide = () => {
return (
<View style={{height: 1}}/>
)
};
_renderFooter() {
if (this.state.showFoot === 1) {
return HttpRequest.renderMoreDataEmptyView();
} else if (this.state.showFoot === 2) {
return HttpRequest.renderMoreDataLoadingView();
} else if (this.state.showFoot === 0) {
return HttpRequest.renderMoreDataNoneView();
}
}
_onEndReached() {
//如果是正在加載中或沒有更多數據了,則返回
if (this.state.showFoot != 0) {
return;
}
//如果當前頁大於或等於總頁數,那就是到最后一頁了,返回
if ((pageNo != 1) && (pageNo >= totalPage)) {
return;
} else {
pageNo++;
}
//底部顯示正在加載更多數據
this.setState({
showFoot: 2,
isLoading: true,
});
//獲取數據
this.fetchData(baseUrl + pageNo + '.json', pageNo);
}
render() {
//第一次加載等待的view
if (this.state.isRefreshing && !this.state.error) {
return HttpRequest.renderLoadingView();
} else if (this.state.error) {
//請求失敗view
return HttpRequest.renderErrorView(this.state.error);
}
//加載數據
return this.renderData();
}
renderData() {
return (
<FlatList
data={this.state.data}
keyExtractor={this._keyExtractor}
renderItem={this._renderItem}
ItemSeparatorComponent={this._itemDivide}
// 方法1)
// numColumns ={2} // 一行2個
// 方法2)
contentContainerStyle={styles.listViewStyle}
//下拉刷新
refreshControl={
<RefreshControl
refreshing={this.state.isRefreshing}
onRefresh={this._onRefresh.bind(this, 0)}
/>
}
//上拉加載
ListFooterComponent={this._renderFooter.bind(this)}
onEndReached={this._onEndReached.bind(this)}
onEndReachedThreshold={1}
/>
);
}
}
module.exports = ImagePage;
樣式:
listViewStyle: { // 主軸方向 flexDirection: 'row', // 一行顯示不下,換一行 flexWrap: 'wrap', // 側軸方向 alignItems: 'center', // 必須設置,否則換行不起作用 },
參考:
https://blog.csdn.net/a_zhon/article/details/78137936
本博客地址: wukong1688
本文原文地址:https://www.cnblogs.com/wukong1688/p/10851764.html
轉載請著名出處!謝謝~~
