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={{ 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,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={{ 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'
}
});