FlatList清單
FlatList是一個高性能的清單元件。原理是:隻負責渲染目前可見的清單項,對于不可見的項将不會渲染因為可見的項總是有限的,當一個項被劃出螢幕後,被滑出項的容器将會成為新滑入的項的容器而不會重新再渲染一個,是以性能要比ScrollView和ListView元件高。
下面是一個原理簡圖:
FlatList的屬性和方法:
屬性 | 描述 |
style | 顯示樣式 |
data | 資料源,格式為對象數組,如[{key:1},{key:2}] |
renderItem | 清單項渲染函數,資料來源于資料源周遊出的每個對象 |
showsVerticalScrollIndicator | 當此屬性為true的時候,顯示一個垂直方向的滾動條,預設為: true |
showsHorizontalScrollIndicator | 當此屬性為true的時候,顯示一個水準方向的滾動條,預設為: true |
pagingEnabled | 當值為true時,滾動條會停在滾動視圖的尺寸的整數倍位置。預設為: false |
ItemSeparatorComponent | 行與行之間的分隔線元件。不會出現在第一行之前和最後一行之後 |
ListEmptyComponent | 清單為空時渲染該元件。可以是 React Component, 也可以是一個 render 函數,或者渲染好的 element |
ListFooterComponent | 清單尾部元件。可以是 React Component, 也可以是一個 render 函數,或者渲染好的 element |
ListHeaderComponent | 清單頭部元件。可以是 React Component, 也可以是一個 render 函數,或者渲染好的 element |
numColumns | 多列布局隻能在非水準模式下使用,即必須是horizontal={false}。此時元件内元素會從左到右從上到下按 Z 字形排列。如numColumns = {2}表示清單顯示兩列 |
columnWrapperStyle | 當numColumns大于1時才可用,表示指定此樣式作用在每行容器上。如{{backgroundColor:'red'}} |
horizontal | 設定為 true 則變為水準布局模式,預設為: false |
initialNumToRender | 指定一開始渲染的元素數量,最好剛剛夠填滿一個螢幕,這樣保證了用最短的時間給使用者呈現可見的内容。注意這第一批次渲染的元素不會在滑動過程中被解除安裝,這樣是為了保證使用者執行傳回頂部的操作時,不需要重新渲染首批元素 |
inverted | 翻轉滾動方向 |
onEndReachedThreshold | 決定當距離内容最底部還有多遠時觸發onEndReached回調,範圍0~1,如0.01表示觸底時觸發 |
onEndReached | 在清單底部往下滑時觸發該函數。表示當清單被滾動到距離内容最底部不足onEndReachedThreshold的距離時調用 |
scrollEnabled | 當為false時表示禁止滾動,預設為: true |
onMomentumScrollBegin | 滾動慣性動畫開始時觸發的函數 |
onMomentumScrollEnd | 滾動慣性動畫結束時觸發的函數 |
onScrollBeginDrag | 拖拽開始時觸發的函數 |
onScrollEndDrag | 拖拽結束時觸發的函數 |
onRefresh | 在清單頂部往下滑時觸發該函數。如果設定了此選項,則會在清單頭部添加一個标準的RefreshControl控件,以便實作“下拉重新整理”的功能,此時顯示的loading符号為預設樣式,需要自定義樣式可使用refreshControl |
refreshing | 在等待加載新資料時将此屬性設為 true,清單就會顯示出一個正在加載的符号,此時顯示的loading符号為預設樣式,需要自定義樣式可使用refreshControl |
refreshControl | RefreshControl元件,可以自定義loading符号的樣式,(該屬性在中文官網中沒有找到,應該是作者忽略了) |
方法 | 描述 |
scrollToEnd() | 滾動到最底部 |
scrollToIndex() | 将位于索引值為index的元素滾動到可視區域首行位置,如scrollToIndex({animated: true, index:10}); |
flashScrollIndicators() | 短暫地顯示滾動訓示器 |
貼上代碼:
import React, { Component } from 'react';
import { View, Text, FlatList, StyleSheet,RefreshControl } from 'react-native';
class FlatListComp extends Component {
state = {
list: [],
refreshing: false
};
componentDidMount(){
// 初始化資料
let list = [];
for(var i = 0; i < 8; i++) {
list.push({key: 'key'+(i+1)});
}
this.setState({list: list});
}
// 渲染清單項
_renderItem = ({index, item}) => {
console.log(index);
return (
<View key={item.key} style={styles.itemViewStyle}>
<Text style={styles.itemTextStyle}>{item.key}</Text>
</View>
);
}
// 分割線
_renderSeparator = () => {
return (
class Separator extends Component {
render(){
return (
<View style={styles.separatorStyle} />
);
}
}
);
}
_renderListEmptyComp = () => {
return (
<View>
<Text>沒有資料時顯示本段文字</Text>
</View>
);
}
// 底部加載
_onEndReached = () => {
this.setState({refreshing: true});
// 關于更新state裡數組的兩種方式
//setState({ 'arrary': [...this.state.array, newItem]}).
//setState({ 'array' : [...this.state.array].concat(newList|newItem)}).
let newList = [];
for(var i = 0; i < 3; i++) {
newList.push({key: '(new)key'+ Math.floor(Math.random() * 10000)});
}
setTimeout(()=>{
this.setState({list: [...this.state.list].concat(newList), refreshing: false});
},2000);
}
// 頂部加載
_onRefresh = () => {
this.setState({refreshing: true});
setTimeout(()=>{
this.setState({refreshing: false});
// this.myFlatList.scrollToEnd(); // 滾動到底部
// this.myFlatList.scrollToIndex({animated: true, index:10}); // 将位于索引值為index的元素滾動到可視區域首行位置
// this.myFlatList.flashScrollIndicators(); // 短暫地顯示滾動訓示器
},2000);
}
render() {
console.log(this.state.list);
return (
<View style={{flex:1}}>
<View style={styles.headerViewStyle}>
<Text style={styles.headerTextStyle}>我的APP</Text>
</View>
<FlatList
style={styles.scrollViewStyle}
ref={(view) => { this.myFlatList = view; }}
data={this.state.list} // 資料源
renderItem={this._renderItem} // 從資料源中挨個取出資料并渲染到清單中
showsVerticalScrollIndicator={false} // 當此屬性為true的時候,顯示一個垂直方向的滾動條,預設為: true
showsHorizontalScrollIndicator={false} // 當此屬性為true的時候,顯示一個水準方向的滾動條,預設為: true
ItemSeparatorComponent = {this._renderSeparator()} // 行與行之間的分隔線元件。不會出現在第一行之前和最後一行之後
ListEmptyComponent = {this._renderListEmptyComp()} // 清單為空時渲染該元件。可以是 React Component, 也可以是一個 render 函數,或者渲染好的 element
onEndReachedThreshold={0.01} // 決定當距離内容最底部還有多遠時觸發onEndReached回調,範圍0~1,如0.01表示觸底時觸發
onEndReached={this._onEndReached} // 在清單底部往下滑時觸發該函數。表示當清單被滾動到距離内容最底部不足onEndReachedThreshold的距離時調用
refreshControl={
<RefreshControl
refreshing={this.state.refreshing} // 在等待加載新資料時将此屬性設為 true,清單就會顯示出一個正在加載的符号
onRefresh={this._onRefresh.bind(this)} // 在清單頂部往下滑時觸發該函數。如果設定了此選項,則會在清單頭部添加一個标準的RefreshControl控件,以便實作“下拉重新整理”的功能
tintColor="#ffffff" // 指定重新整理訓示器的背景色(iOS)
title="加載中..." // 指定重新整理訓示器下顯示的文字(iOS)
titleColor="#000000" // 指定重新整理訓示器下顯示的文字的顔色(iOS)
colors={['#ff0000', '#00ff00', '#0000ff']} // 重新整理訓示器在重新整理期間的過渡顔色(Android)
progressBackgroundColor="#ffffff" // 指定重新整理訓示器的背景色(Android)
/>
}
/>
</View>
);
}
}
const styles = StyleSheet.create({
scrollViewStyle: {
flex: 1,
marginLeft:10,
marginRight: 10,
marginBottom: 10
},
headerViewStyle: {
height: 50,
backgroundColor: '#f4511e',
justifyContent: 'center',
alignItems: 'center'
},
headerTextStyle: {
fontSize: 20,
color: '#FFFFFF'
},
itemViewStyle: {
height: 100,
borderWidth: 1,
borderRadius: 10,
marginTop: 5,
justifyContent: 'center',
alignItems: 'center'
},
itemTextStyle: {
color: 'red',
fontSize: 20
},
separatorStyle: {
borderColor: '#A4A4A4',
borderBottomWidth: 2,
marginTop: 5
}
});
export default FlatListComp;
效果:
小貼士:由于加載的loading符号形狀是不可變的,如果你想要更個性化的清單元件,可以嘗試使用第三方插件 react-native-pull 。
SectionList清單組
SectionList清單組和FlatList的原理是差不多的,在顯示上,每個組裡的項就是一個清單,要注意的是資料源格式的不同。
資料源的格式如下所示:
datasource=[
{
title:'section1',
...
data:[
{key:1},
{key:2}
]
}, ...]
在屬性和方法上,大部分也和FlatList一樣的,相同的這裡就不列出來了。SectionList特有的屬性和方法:
屬性 | 描述 |
---|---|
sections | 清單組資料源 |
renderSectionHeader | 每個組的頭部元件 |
renderSectionFooter | 每個組的尾部元件 |
stickySectionHeadersEnabled | 當下一個section把它的前一個section的可視區推離螢幕的時候,讓這個section的header粘連在螢幕的頂端。預設為: false |
SectionSeparatorComponent | 組與組之間的分割線元件 |
方法 | 描述 |
---|---|
scrollToLocation() | 将位于索引值為sectionIndex中itemIndex的元素滾動到可視區域首行位置,如scrollToLocation({animated: true, itemIndex:2, sectionIndex:1}); |
貼上代碼(本demo中代碼有點多,因為列出了所有的清單組屬性,請仔細看):
import React, {Component} from 'react';
import { View, Text, SectionList, StyleSheet, RefreshControl } from 'react-native';
class SectionListComp extends Component {
state = {
sections: [],
refreshing: false
};
componentDidMount() {
let sections = [];
for(var i = 0; i < 4; i++) {
let section = {};
section.title = '清單組'+ (i+1);
section.data = [];
for(var n = 0; n < 5; n++) {
let item = {};
item.key = 'key' + (n+1);
section.data.push(item);
}
sections.push(section);
}
this.setState({sections: sections});
}
_renderSectionHeader = ({section: {title}}) => {
return (
<View style={styles.titleViewStyle}>
<Text style={styles.titleTextStyle}>{title}</Text>
</View>
);
}
_renderItem = ({ item, index, section }) => {
return (
<View style={styles.itemViewStyle}>
<Text style={styles.itemTextStyle} key={item.key}>{item.key}</Text>
</View>
);
}
_renderListEmptyComp = () => {
return (
<View>
<Text>沒有資料時顯示本段文字</Text>
</View>
);
}
// 分割線
_renderSeparator = () => {
return (
class Separator extends Component {
render(){
return (
<View style={styles.separatorStyle} />
);
}
}
);
}
// 底部加載
_onEndReached = () => {
this.setState({refreshing: true});
// 關于更新state裡數組的兩種方式
//setState({ 'arrary': [...this.state.array, newItem]}).
//setState({ 'array' : [...this.state.array].concat(newList|newItem)}).
let sections = [...this.state.sections];
let section = {};
section.title = '(new)清單組'+ Math.floor(Math.random() * 10000);
section.data = [];
for(var n = 0; n < 5; n++) {
let item = {};
item.key = 'key' + n;
section.data.push(item);
}
sections.push(section);
setTimeout(()=>{
this.setState({sections: sections, refreshing: false});
},2000);
}
// 頂部加載
_onRefresh = () => {
this.setState({refreshing: true});
setTimeout(()=>{
this.setState({refreshing: false});
// this.mySectionList.scrollToLocation({animated: true, itemIndex:2, sectionIndex:1}); // 将位于索引值為sectionIndex中itemIndex的元素滾動到可視區域首行位置
// this.myFlatList.flashScrollIndicators(); // 短暫地顯示滾動訓示器
},2000);
}
render() {
return (
<View style={{flex:1}}>
<View style={styles.headerViewStyle}>
<Text style={styles.headerTextStyle}>我的APP</Text>
</View>
<SectionList
ref={(view) => { this.mySectionList = view; }}
style={styles.scrollViewStyle}
sections={this.state.sections}
renderItem={this._renderItem}
renderSectionHeader={this._renderSectionHeader} // 每個組的頭部元件
renderSectionFooter={()=>{}} // 每個組的尾部元件
ListHeaderComponent = {()=><View />} // 頭部元件。可以是 React Component, 也可以是一個 render 函數,或者渲染好的 element
ListFooterComponent = {()=><View />} // 尾部元件。可以是 React Component, 也可以是一個 render 函數,或者渲染好的 element
ListEmptyComponent = {this._renderListEmptyComp()} // 清單為空時渲染該元件。可以是 React Component, 也可以是一個 render 函數,或者渲染好的 element
// ItemSeparatorComponent = {this._renderSeparator()} // 行與行之間的分隔線元件。不會出現在第一行之前和最後一行之後
// SectionSeparatorComponent = {this._renderSeparator()} // 組與組之間的分割線元件
inverted={false} // 翻轉滾動方向。預設為: false
stickySectionHeadersEnabled = {true} // 當下一個section把它的前一個section的可視區推離螢幕的時候,讓這個section的header粘連在螢幕的頂端。預設為: false
horizontal= {false} // 設定為 true 則變為水準布局模式,預設為: false
showsVerticalScrollIndicator={false} // 當此屬性為true的時候,顯示一個垂直方向的滾動條,預設為: true
showsHorizontalScrollIndicator={false} // 當此屬性為true的時候,顯示一個水準方向的滾動條,預設為: true
scrollEnabled={true} // 當為false時表示禁止滾動,預設為: true
onEndReachedThreshold={0.01} // 決定當距離内容最底部還有多遠時觸發onEndReached回調,範圍0~1,如0.01表示觸底時觸發
onEndReached={this._onEndReached} // 表示當清單被滾動到距離内容最底部不足onEndReachedThreshold的距離時調用
onMomentumScrollBegin={()=>{}} // 滾動慣性動畫開始時觸發的函數
onMomentumScrollEnd={()=>{}} // 滾動慣性動畫結束時觸發的函數
onScrollBeginDrag={()=>{}} // 拖拽開始時觸發的函數
onScrollEndDrag={()=>{}} // 拖拽結束時觸發的函數
// initialNumToRender={6} // 指定一開始渲染的元素數量,最好剛剛夠填滿一個螢幕,這樣保證了用最短的時間給使用者呈現可見的内容。注意這第一批次渲染的元素不會在滑動過程中被解除安裝,這樣是為了保證使用者執行傳回頂部的操作時,不需要重新渲染首批元素
// keyExtractor={(item, index) => item + index} // 當item沒有key屬性時,可以通過該函數生成一個不重複的key值
// onRefresh={this._onRefresh} // 如果設定了此選項,則會在清單頭部添加一個标準的RefreshControl控件,以便實作“下拉重新整理”的功能
// refreshing={this.state.refreshing} // 在等待加載新資料時将此屬性設為 true,清單就會顯示出一個正在加載的符号
或
refreshControl={
<RefreshControl
refreshing={this.state.refreshing} // 在等待加載新資料時将此屬性設為 true,清單就會顯示出一個正在加載的符号
onRefresh={this._onRefresh.bind(this)} // 在清單頂部往下滑時觸發該函數。如果設定了此選項,則會在清單頭部添加一個标準的RefreshControl控件,以便實作“下拉重新整理”的功能
tintColor="#ffffff" // 指定重新整理訓示器的背景色(iOS)
title="加載中..." // 指定重新整理訓示器下顯示的文字(iOS)
titleColor="#000000" // 指定重新整理訓示器下顯示的文字的顔色(iOS)
colors={['#ff0000', '#00ff00', '#0000ff']} // 重新整理訓示器在重新整理期間的過渡顔色(Android)
progressBackgroundColor="#ffffff" // 指定重新整理訓示器的背景色(Android)
/>
}
/>
</View>
);
}
}
const styles = StyleSheet.create({
scrollViewStyle: {
flex: 1,
marginLeft: 10,
marginRight: 10
},
headerViewStyle: {
height: 50,
backgroundColor: '#f4511e',
justifyContent: 'center',
alignItems: 'center'
},
headerTextStyle: {
fontSize: 20,
color: '#FFFFFF'
},
titleViewStyle: {
backgroundColor: '#E4E4E4',
marginTop: 20,
height: 30,
justifyContent: 'center',
alignItems: 'center'
},
titleTextStyle: {
color: 'red',
fontSize: 24
},
itemViewStyle: {
height: 70,
borderWidth: 1,
borderRadius: 10,
marginTop: 5,
justifyContent: 'center',
alignItems: 'center'
},
itemTextStyle: {
color: 'red',
fontSize: 20
},
separatorStyle: {
borderColor: 'blue',
borderBottomWidth: 1,
marginTop: 5,
marginBottom: 5
}
});
export default SectionListComp;
效果: