SectionList可以用於展示有多個分區的列表。
SectionList常用屬性和方法
sections: Array相當於ListView中的數據源,SectionList所需要的數據都是經由sections屬性傳入,數據類型為Array類型
renderItem: (info: {item: Item, index: number}) => ?React.Element renderItem返回Section中的每個小的的Item。可以通過函數返回Element,函數有一個info參數,參數為JSON形式,參數形式為:{item: Item, index: number}。
renderSectionHeader: (info: {section: SectionT}) => ?React.Element renderSectionHeader返回每個Section的標志性頭部,可以通過函數返回Element,函數有一個info參數,參數為JSON形式,參數形式為:{section:{key : number, data : [ Object, Object, …] }}。
refreshing: boolean 是否處於刷新狀態。
onRefresh: () => void 通過函數改變refreshing從而控制刷新與否。
ItemSeparatorComponent : ReactClass item之間的分隔線組件。不會出現在第一行之前和最后一行之后。
SectionSeparatorComponent : ReactClass .每個section之間的分隔組件。
ListHeaderComponent : ReactClass SectionList頭部組件。
ListFooterComponent : ReactClass SectionList尾部組件。
keyExtractor: (item: Item, index: number) => string 默認情況下每個item都需要提供一個不重復的key屬性,因此可以通過keyExtractor函數為每一個item生成一個唯一的key。
onEndReached : (info: {distanceFromEnd: number}) => void 是否到達底部,在默認情況下會有一個默認的distanceFromEnd臨界值。可以通過此屬性來達到上拉加載的效果。
onEndReachedThreshold number 調用onEndReached之前的臨界值,單位是像素
注意點:
/**
* 將數據轉化為sectionList需要的數據格式
* @param data
* @returns {Array}
*/
changeGoodsData(data){
let jsonData = data
//每組的開頭在列表中的位置
let totalSize = 0;
//SectionList的數據源
let cityInfos = [];
//分組頭的數據源
let citySection = [];
//分組頭在列表中的位置
let citySectionSize = [];
for (let i = 0; i < jsonData.length; i++) {
citySectionSize[i] = totalSize;
//給右側的滾動條進行使用的
citySection[i] = jsonData[i].catName;
let section = {}
section.key = jsonData[i].catName;
section.data = jsonData[i].goods;
for (let j = 0; j < section.data.length; j++) {
section.data[j].key = j
}
cityInfos[i] = section;
//每一項的header的index
totalSize += section.data.length + 1
}
return cityInfos;
}
實例
import React, {PureComponent} from 'react';
import {FlatList, TouchableOpacity, Text, View, TextInput, StyleSheet, Image, Alert,SectionList} from 'react-native';
import {Actions, ActionConst} from 'react-native-router-flux';
import Button from "apsl-react-native-button"//自定義button
import {color, tv_size} from "../../common/Constants";
import src from "../../common/Image";
export default class TodayLeadingAddPage extends PureComponent {
dataContainer = [];
constructor(props) {
super(props);
this.state = {
/**假設1為選擇,2為取消*/
sourceData: [
{ key: "招牌菜-3", data: [{ title: "魚香茄子",type:1 }, { title: "酸菜魚",type:2 }, { title: "紅燒肉",type:1 }] },
{ key: "涼菜-12", data: [{ title: "花生米" ,type:2}, { title: "黃瓜",type:1 }] },
{ key: "主食-8", data: [{ title: "米飯" ,type:1},] },
]
, selected: (new Map(): Map<String, boolean>)
, refreshing: false
, indexText: ''
}
}
componentDidMount() {
}
/**
* 此函數用於為給定的item生成一個不重復的Key。
* Key的作用是使React能夠區分同類元素的不同個體,以便在刷新時能夠確定其變化的位置,減少重新渲染的開銷。
* 若不指定此函數,則默認抽取item.key作為key值。若item.key也不存在,則使用數組下標
*
* @param item
* @param index
* @private
*/
_keyExtractor = (item, index) => index;
/**
* 使用箭頭函數防止不必要的re-render;
* 如果使用bind方式來綁定onPressItem,每次都會生成一個新的函數,導致props在===比較時返回false,
* 從而觸發自身的一次不必要的重新render,也就是FlatListItem組件每次都會重新渲染。
*
* @param id
* @private
*/
_onPressItem = (id: string) => {
this.setState((state) => {
const selected = new Map(state.selected);
selected.set(id, !selected.get(id));
return {selected}
});
//CustomToastAndroid.show(JSON.stringify(id), CustomToastAndroid.SHORT);
};
// 下拉刷新
_renderRefresh = () => {
this.setState({refreshing: true})//開始刷新
//這里模擬請求網絡,拿到數據,3s后停止刷新
setTimeout(() => {
//CustomToastAndroid.show('沒有可刷新的內容!', CustomToastAndroid.SHORT);
this.setState({refreshing: false});
}, 1000);
};
// 上拉加載更多
_onEndReached = () => {
};
/**點擊選擇或者取消*/
clickItem(item){
if(item.type===1){
alert('選擇');
}else
{
alert('取消');
}
}
/**單元格*/
_renderItem = ({item}) => {
return (
<FlatListItem
id={item.id}
type={item.type}
onClick={()=>this.clickItem(item)}
onPressItem={this._onPressItem}
selected={!!this.state.selected.get(item.id)}
title={item.title}
/>
);
};
/**區頭*/
_sectionComp = (info) => {
var txt = info.section.key;
return (<View style={{height: 50, backgroundColor: 'white'}}>
<View style={{height:10,backgroundColor:'#eee'}}>
</View>
<View style={{height: 40, backgroundColor: 'white',justifyContent:'center'}}>
<Text
style={{color: color.color_grey_3, fontSize:tv_size.dp30,marginLeft:10}}>
{txt}
</Text>
</View>
<Image source={src.line} style={{width: null, height: 1}} resizeMode='stretch'/>
</View>);
}
render() {
return (
<View style={{flex:1}}>
<SectionList
ref={ref => this.SectionList = ref}
renderSectionHeader={this._sectionComp}
renderItem={this._renderItem}
sections={this.state.sourceData}
extraData={this.state.selected}
keyExtractor={this._keyExtractor}
onEndReachedThreshold={0.1}
// 當列表被滾動到距離內容最底部不足onEndReacchedThreshold設置的距離時調用
onEndReached={this._onEndReached}
refreshing={this.state.refreshing}
onRefresh={this._renderRefresh}
/>
</View>
);
}
}
class FlatListItem extends React.PureComponent {
_onPress = () => {
this.props.onPressItem(this.props.id);
};
render() {
return (
<TouchableOpacity
{...this.props}
onPress={this._onPress}
>
<View style={{
backgroundColor: '#eee',
}}>
<View style={styles.item_container}>
<View style={{flexDirection: 'row', alignItems: 'center'}}>
<Image style={{marginLeft:10,height:64,width:64,backgroundColor:'red',borderRadius:5}}/>
<View style={{margin: 15}}>
<Text style={{color: color.color_grey_3, fontSize: tv_size.dp32}}>{this.props.title}</Text>
<View style={{flexDirection: 'row', marginTop: 10}}>
<Text style={{color: color.color_grey_6, fontSize: tv_size.dp24}}>現價:</Text>
<Text style={{color: color.color_org_red, fontSize: tv_size.dp24}}>¥28</Text>
</View>
<View style={{flexDirection: 'row', marginTop: 10,}}>
<Text style={{color: color.color_grey_6, fontSize: tv_size.dp24,textDecorationLine:'line-through'}}>原價:¥28</Text>
</View>
</View>
</View>
<View style={{alignSelf:'flex-end',marginBottom:10,marginRight: 10}}>
<TouchableOpacity onPress={this.props.onClick}>
<Image source={this.props.type===1? src.ic_goods_select:src.ic_goods_cancel} />
</TouchableOpacity>
</View>
</View>
<Image source={src.line} style={{width: null, height: 1}} resizeMode='stretch'/>
</View>
</TouchableOpacity>
);
}
}
var styles = StyleSheet.create({
base_view: {flex: 1, backgroundColor: '#eee'},
text_item: {
padding: 10, flex: 1, backgroundColor: '#fff', borderWidth: 1,
borderColor: '#0f80ff', marginLeft: 10
},
item_container: {
backgroundColor: 'white',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between'
}
});