FlatList是ReactNative中一个常用控件,类似Android中的ListView,实质是基于<VirtulizedList>组件的封装。一个高性能的,用于渲染的列表组件,常见属性如下:
data - 数据源
renderItem - 列表呈现方式
extraData - 用于告诉列表重新渲染,因为它实现了PureComponent,但是props浅拷贝是不会重新渲染的
onEndReached - 下拉加载触发的函数
onEndReachedThreshold - 决定当距离内容最底部还有多远时触发onEndReached回调
onRefresh - 上拉刷新触发的函数
refreshing - 在等待加载新数据时将此属性设为true,列表就会显示出一个正在加载的符号
栗子1:
import React, {Component} from 'react';
import {
FlatList,
StyleSheet,
Text,
View,
Image,
Dimensions,
} from 'react-native';
var {height, width} = Dimensions.get('window');
export default class FlatListBasics extends Component<Props> {
constructor(props) {
super(props);
let arr = new Array();
for (let i = 0; i < 20; i++) {
arr[i] = {key: i + '',title: '测试数据' + i,};
}
this.state = {
data: arr,
};
}
_renderItem = ({item}) => {
return (
<View style={styles.mainLine}>
<Text style={styles.lineId}>{item.key}</Text>
<Text style={styles.lineTitle}>{item.title}</Text>
</View>
);
};
render() {
return (
<View style={styles.container}>
<FlatList data={this.state.data} renderItem={this._renderItem} />
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1, // 填充满整个屏幕
alignItems: 'center',
// backgroundColor: "red"
},
mainLine: {
width:width - 20,
backgroundColor: 'red',
flexDirection: 'row',
},
lineId: {
flex:1,
fontSize: 30,
backgroundColor: 'blue',
},
lineTitle: {
flex:2 ,
fontSize: 25,
backgroundColor: 'yellow',
},
});
栗子2:
import React from 'react';
import { StyleSheet, Text, View, FlatList, Dimensions } from 'react-native';
const data =[
{ key: 'A' }, { key: 'B' }, { key: 'C' }, { key: 'D' }, { key: 'E' }, { key: 'F' }, { key: 'G' }, { key: 'H' }, { key: 'I' }, { key: 'J' },
{ key: 'K' },
];
const formatData = (data, numColumns) => {
const numberOfFullRows = Math.floor(data.length / numColumns);
let numberOfElementsLastRow = data.length -(numberOfFullRows*numColumns);
while(numberOfElementsLastRow !== numColumns && numberOfElementsLastRow !== 0){
data.push({key: 'blank-${numberOfElementsLastRow}',empty:true})
numberOfElementsLastRow++;
}
return data;
};
const numColumns = 4;
export default class GridPlay extends React.Component {
renderItem = ({item , index}) => {
if(item.empty === true) {
return <View style={[styles.item,styles.itemInvisible]} />
}
return (
<View
style={styles.item}
>
<Text style={styles.itemText}>{item.key}</Text>
</View>
);
}
render() {
return (
<FlatList
data={ formatData(data, numColumns)}
style={styles.container}
renderItem={this.renderItem}
numColumns={4}
/>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
marginVertical: 20,
},
item: {
backgroundColor: '#4D243D',
alignItems: 'center',
justifyContent: 'center',
flex: 1,
margin: 3,
height:Dimensions.get('window').width / numColumns,
},
itemInvisible: {
backgroundColor: 'transparent',
},
itemText: {
color: '#fff',
},
});
栗子3:
const numColumns = 2;
const formatData = (data: any, numColumns: any) => {
const numberOfFullRows = Math.floor(data.length / numColumns);
let numberOfElementsLastRow = data.length - numberOfFullRows * numColumns;
while (numberOfElementsLastRow !== numColumns && numberOfElementsLastRow !== 0) {
data.push({ key: `blank-${numberOfElementsLastRow}`, empty: true });
numberOfElementsLastRow++;
}
return data;
};
export class MyComponent extends React.Component<{}, BadgeInfoState> {
constructor(props: any) {
super(props);
this.state = {
badgeData: [],
showSpinner: false,
badgeTitle: '',
showBadgeDetailModal: false,
itemBadge: ''
};
}
async componentDidMount() {
this.setState({ showSpinner: true });
const resultBadges: any = await DataAccess.getBadges();
const levels = JSON.stringify(resultBadges[0]);
const levelsSub = JSON.parse(levels);
const t = levelsSub.badges;
this.setState({
badgeData: t,
badgeTitle: resultBadges[0].level
});
}
formatImgs() {
const ImgItems: any = [];
console.log(' formatImgs ', this.state.badgeData.length);
_.forEach(this.state.badgeData, (item: any) => {
ImgItems.push(
<View style={styles.itemContentContainer}>
<Image style={styles.itemImagDetail} source={showIntegralActions(item.badge_image_url)} />
<Text>{item.badgeTitle}</Text>
</View>
);
});
return ImgItems;
}
onClose = () => {
console.log('BadgesComponent onClose');
this.setState({ showBadgeDetailModal: false });
};
_onPress = (item: any) => {
console.log('_onPress item= ', item);
this.setState({
showBadgeDetailModal: true,
itemBadge: item
});
};
renderItem = ({ item }) => {
if (item.empty === true) {
return <View style={[styles.itemStyle, styles.itemInvisible]} />;
}
return (
<View style={styles.itemStyle}>
<TouchableOpacity onPress={() => this._onPress(item)}>
<Image style={styles.itemImagDetail} source={showIntegralActions(item.badge_image_url)} />
<Text>{item.badgeTitle}</Text>
</TouchableOpacity>
</View>
);
};
formatImgGrid() {
console.log(' formatImgGrid ');
return (
<FlatList
data={formatData(this.state.badgeData, numColumns)}
style={styles.container}
renderItem={this.renderItem}
numColumns={2}
/>
);
}
render() {
return (
<Content>
<Header noShadow={true} style={styles.headerDetail}>
<Left>
<Button transparent={true}>
<Icon name='angle-left' type='FontAwesome' style={styles.colorBlackDetail} />
</Button>
</Left>
<Body>
<Title style={styles.textContentDetail}>Badges</Title>
</Body>
</Header>
<Text style={styles.badgeTitle}>{this.state.badgeTitle}</Text>
<View style={styles.itemContainer}>{this.formatImgGrid()}</View>
<Modal
animationType='slide'
transparent={false}
visible={this.state.showBadgeDetailModal}
onRequestClose={() => {}}>
<BadgesDetailComponent closeModal={this.onClose} itemBadge={this.state.itemBadge} />
</Modal>
</Content>
);
}
}