效果图:
FlatListPage文件
头文件包含
import {
ActivityIndicator,
Alert,
Dimensions,
FlatList,
Image,
RefreshControl,
StyleSheet,
Text,
TouchableOpacity,
View
} from 'react-native';
import {XLImageButton} from "../common/XLButton";
import {NavigationBarTitle} from "../common/NavigationBarTitle";
import {appStyle} from "../style/BaseStyles";
列表json数据
const list = [{
title: '美仁枣300g',
imageUrl: 'https://a.vpimg4.com/upload/merchandise/pdcvis/602520/2018/0611/93/7f380e8c-627e-4162-b68c-a16ad98f9609_5t.jpg',
price: 38,
}, {
title: '2件起售】香蕉干90g',
imageUrl: 'https://a.vpimg2.com/upload/merchandise/pdcvis/610789/2018/0420/114/54c7ae6a-1b94-44d9-bd38-0d46326aa683_t.jpg',
price: 19,
}, {
title: '【2件起售】七彩葡萄干420g',
imageUrl: 'https://a.vpimg3.com/upload/merchandise/pdcvis/602520/2018/0611/81/faf4abe6-e212-4347-9369-118028bec2fe_5t.jpg',
price: 27,
}, {
title: '优你康罐装牛奶双味棒棒糖720g',
imageUrl: 'https://a.vpimg3.com/upload/merchandise/pdcvis/605346/2018/0509/184/5a1c29d8-b127-40c5-b239-4b0c5b5b1e1b.jpg',
price: 128,
}, {
title: '滇园南枣核桃糕148g*2福建特产小吃休闲糖果零食软糖喜糖',
imageUrl: 'https://a.vpimg4.com/upload/merchandise/pdcvis/606282/2018/0424/132/5bf877ba-9a13-4f85-a67c-2ea2fbbe13f9_t.jpg',
price: 59,
}, {
title: '【2件起售】自然派榴莲糖200g',
imageUrl: 'https://a.vpimg2.com/upload/merchandise/pdcvis/605222/2018/0320/1/9edf6130-35f1-4af8-9034-bf37a617c82a.jpg',
price: 22,
}, {
title: '【乐奈】8口味速融巧克力408g',
imageUrl: 'https://a.vpimg3.com/upload/merchandise/pdcvis/131932/2018/0530/137/083642ef-5fef-446c-b279-7a3047ba058e_5t.jpg',
price: 39,
}, {
title: '【BK】魔彩巧克力礼盒250g',
imageUrl: 'https://a.vpimg3.com/upload/merchandise/pdcvis/600876/2018/0324/158/b3fed03e-3cd8-40c7-b53d-19630adb2d31_t.jpg',
price: 86,
}, {
title: '【2件起售】乐奈烤巧克力72g',
imageUrl: 'https://a.vpimg3.com/upload/merchandise/pdcvis/131932/2017/1223/15/060b8ff9-674e-4869-9845-a8aee1f435a9_t.jpg',
price: 22,
}, {
title: '每日坚果A款混合果仁果干孕妇零食坚果小礼盒175克',
imageUrl: 'https://a.vpimg4.com/upload/merchandise/pdcvis/602656/2018/0313/108/924c4a5b-7315-40bd-9d5f-84fb2fd489a2.jpg',
price: 39,
}, {
title: '每日坚果A款混合果仁果干孕妇零食坚果礼盒750克',
imageUrl: 'https://a.vpimg2.com/upload/merchandise/pdcvis/2018/04/25/144/2a6462ca-bc0a-4ffb-9f43-d1e6fae63baf_235x297_90.jpg',
price: 199,
}, {
title: '鹰嘴豆250g',
imageUrl: 'https://a.vpimg3.com/upload/merchandise/pdcvis/602520/2018/0611/195/11f3c35b-12dc-4263-ad80-f2fa9a5b5c37_5t.jpg',
price: 16,
}, {
title: '【2件起售】蔓越莓干核桃仁118g',
imageUrl: 'https://a.vpimg3.com/upload/merchandise/pdcvis/602520/2018/0611/74/5b521a8e-2b51-41a4-b120-3e06e799be1b_5t.jpg',
price: 28,
},
];
FlatListPage类实现
export default class FlatListPage extends Component {
static navigationOptions = ({navigation, screenProps}) => ({
headerStyle: {
backgroundColor: '#fff'
},
headerLeft: ( // 设置左边的标签
<XLImageButton
imageStyle={appStyle.backIcon}
clickAction={() => {
const {goBack} = navigation;
goBack();
}}
/>
),
headerTitle: (
<NavigationBarTitle title={'FlatList'}/>
),
});
constructor(props) {
super(props);
this.state = {
data: [],
isRefreshing: false,
isShowLoadMore: false,
}
}
render() {
return (
<View style={styles.container}>
<FlatList
style={{flex: 1}}
data={this.state.data}
numColumns={column}
horizontal={false}
//注意参数名:item 是固定的
renderItem={({item, index}) => {
return <TouchableOpacity
style={styles.cellStyle}
onPress={() => {
Alert.alert(item.title);
}}
opacity={0.5}
>
<View style={{flex: 1, alignItems: 'center'}}>
<Image style={{width: window.width / (column + 1), height: window.width / (column + 1)}}
source={{uri: item.imageUrl}}/>
<Text numberOfLines={1}
style={[styles.titleStyle, {textAlign: 'left'}]}>{item.title}</Text>
<Text style={styles.priceStyle}>{'¥' + item.price}</Text>
</View>
</TouchableOpacity>
}}
refreshControl={
<RefreshControl
tintColor="#ff0000"
title="Loading..."
titleColor="#00ff00"
colors={['#ff0000', '#00ff00', '#0000ff']}
progressBackgroundColor="#ffff00"
refreshing={this.state.isRefreshing}
onRefresh={() => {
this.setState({isRefreshing: true});
setTimeout(() => {
this.setState({
isRefreshing: false,
data: list,
});
}, 2000);
}}/>
}
ListEmptyComponent={() => {
return <View style={[styles.container, {alignItems: 'center'}]}>
<Text style={styles.noDataText}>暂无数据...</Text>
</View>
}}
onEndReachedThreshold={0.1}//当前可视列表高度的十分之一
onEndReached={(info: { distanceFromEnd: number }) => {
if (this.state.data.length > 30 || this.state.isShowLoadMore) {//控制是否还有更多可加载
return null;
}
this.setState({
isShowLoadMore: true,//显示加载更多指示器
}, function (finish) {
//拼接数据
const data = this.state.data.concat(list);
setTimeout(() => {
this.setState({
data: data,
}, function (finish) {
this.setState({
isShowLoadMore: false,
})
});
}, 2000);
})
}}
ListFooterComponent={() => {
return this.state.isShowLoadMore ? <View style={styles.indicator}>
<ActivityIndicator
color={'#f00'}
size={'small'}
/>
</View> : null
}}
/>
</View>
)
}
}
本文件样式
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
lineStyle: {
flex: 1,
height: 0.5,
backgroundColor: '#999',
},
cellText: {
lineHeight: 44,
marginHorizontal: 15,
color: '#666',
},
headerStyle: {
height: 40,
justifyContent: 'center',
paddingHorizontal: 10,
backgroundColor: "#ffead1"
},
cellStyle: {
marginVertical: 10,
width: window.width / column,
},
titleStyle: {
padding: 5,
color: '#666',
},
priceStyle: {
color: '#f00',
paddingHorizontal: 5,
// textDecorationLine: 'line-through',//删除线
},
indicator: {
height: 30,
alignItems: 'center',
justifyContent: 'center',
},
noDataText: {
color: '#666',
lineHeight: 50
}
});
XLButton 文件实现
/*
* 自定义组件:按钮
*
* */
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {Image, StyleSheet, Text, TouchableOpacity,} from 'react-native';
//文字按钮
export class XLButton extends Component {
static defaultProp = {
title: 'button',//标题
color: '#333',//字体颜色
titleStyle: null,//标题风格text
textAlign: 'center',//文字居中
fontSize: 15,//字体大小
backgroundColor: 'rgba(0,0,0,0)',//背景颜色
borderRadius: 0,//背景圆角
borderColor: '#fff',//边框颜色
borderWidth: 0,//边框宽度
backgroundStyle: null,//背景风格
clickAction: null,//事件点击
tag: 0,//索引标记
data: null,//数据项
};
static propTypes = {
title: PropTypes.string,//标题
color: PropTypes.string,//字体颜色
fontSize: PropTypes.number,//字体大小
textAlign: PropTypes.string,//文字居中
borderRadius: PropTypes.number,//背景圆角
borderColor: PropTypes.string,//边框颜色
borderWidth: PropTypes.number,//边框宽度
clickAction: PropTypes.func,//事件点击
tag: PropTypes.number,//索引标记
data: PropTypes.any,//数据项
};
render() {
return (
<TouchableOpacity
style={[{
backgroundColor: this.props.backgroundColor,
borderWidth: this.props.borderWidth,
borderColor: this.props.borderColor,
borderRadius: this.props.borderRadius
}, this.props.backgroundStyle ? this.props.backgroundStyle : null]}
onPress={() => {
if (this.props.clickAction) {
this.props.clickAction(this.props.tag, this.props.data);
}
}}
>
<Text style={[{
color: this.props.color,
fontSize: this.props.fontSize,
textAlign: this.props.textAlign
},
this.props.titleStyle ? this.props.titleStyle : null]}
>{this.props.title}</Text>
</TouchableOpacity>
);
}
}
//图片按钮
export class XLImageButton extends XLButton {
static defaultProp = {
image: null,
imageUrl: null,
imageStyle: null,
};
static propTypes = {
image: PropTypes.object,
imageUrl: PropTypes.number,
};
constructor(props) {
super(props);
}
render() {
return (
<TouchableOpacity
style={[{
backgroundColor: this.props.backgroundColor,
borderWidth: this.props.borderWidth,
borderColor: this.props.borderColor,
borderRadius: this.props.borderRadius
}, this.props.backgroundStyle ? this.props.backgroundStyle : null]}
onPress={() => {
if (this.props.clickAction) {
this.props.clickAction(this.props.tag, this.props.data);
}
}}
>
<Image style={[this.props.imageStyle ? this.props.imageStyle : styles.imageIcon]}
source={this.props.imageUrl ? {uri: this.props.imageUrl} :
this.props.image ? this.props.image : require('../../res/nav/navBack.png')}
/>
</TouchableOpacity>
);
}
}
const styles = StyleSheet.create({
imageIcon: {
width: 10,
height: 18,
marginHorizontal: 10,
marginVertical: 5,
}
});
公用导航栏适配:NavigationBarTitle
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {Text, View,} from 'react-native';
import {appStyle} from "../style/BaseStyles";
export class NavigationBarTitle extends Component {
static defaultProp = {
title: 'title',//标题
};
static propTypes = {
title: PropTypes.string,//标题
};
render() {
return (
<View style={appStyle.headerTitleStyle}>
<Text style={appStyle.navTitleStyle}>{this.props.title}</Text>
</View>
);
}
}
通用样式文件:BaseStyles
import {StyleSheet,Dimensions} from 'react-native';
const window = Dimensions.get('window');
export const appStyle = StyleSheet.create({
backIcon: {
width: 10,
height: 18,
marginHorizontal: 15,
},
baseTextColor: {
color: '#FE6634',
},
navTitleStyle:{
fontSize:17,
fontWeight:'bold',
color:'#333',
textAlign:'center',
},
viewBGColor:{
backgroundColor:'#f5f5f5',
},
headerTitleStyle:{
width:window.width-120,
justifyContent:'center',
},
});