技术点分析:
在React Native中,ScrollView组件可以使用 stickyHeaderIndices 轻松实现 sticky 效果;而使用ListView组件时,使用 stickyHeaderIndices 则不生效。
如何实现滚动时每个section header会吸顶?
在ListView中要实现 sticky ,需要使用 cloneWithRowsAndSections 方法,将 dataBlob(object), sectionIDs (array), rowIDs (array) 三个值传进去。
dataBlob
dataBlob 包含ListView所需的所有数据(section header 和 rows),在ListView渲染数据时,使用getSectionData 和 getRowData 来渲染每一行数据。 dataBlob 的 key 值包含 sectionID + rowId
sectionIDs
sectionIDs 用于标识每组section。
rowIDs
rowIDs 用于描述每个 section 里的每行数据的位置及是否需要渲染。在ListView渲染时,会先遍历 rowIDs 获取到对应的 dataBlob 数据。
实现代码:
/**
* Sample React Native App
* https://github.com/facebook/react-native
* @flow
*/
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
ListView,
Image,
TouchableOpacity
} from 'react-native';
// 导入外部json数据
var Car = require('./Car.json');
// ES5
var ListViewDemo3 = React.createClass({
// 初始化
getInitialState(){
// 获取section的方法
var getSectionData = (dataBlob,sectionID) => {
return dataBlob[sectionID];
};
var getRowData = (dataBlob,sectionID,rowID) => {
return dataBlob[sectionID +':' + rowID];
};
return {
dataSource: new ListView.DataSource({
getSectionData: getSectionData, // 获取section
getRowData: getRowData, // 获取row
rowHasChanged: (row1,row2)=>row1 !== row2,
sectionHeaderHasChanged: (s1,s2)=>s1 !== s2,
})
}
},
// 复杂的操作:数据请求 或者 异步操作(定时器)
componentDidMount(){
// 调用json数据
this.loadDataFromJson();
},
// 调用json数据的方法
loadDataFromJson(){
// 拿到json数据
var jsonData = Car.data;
// 定义一些变量
var dataBlob = {},
sectionIDs = [],
rowIDs = [],
cars = [];
// 遍历
for(var i=0;i<jsonData.length;i++){
// 1.把组号放入sectionIDs数组
sectionIDs.push(i);
// 2.把组内容放入dataBlob对象中
dataBlob[i] = jsonData[i].title;
// 3.取出该组所有的汽车数据
cars = jsonData[i].cars;
rowIDs[i] = [];
// 4.遍历汽车数据
for(var j=0;j<cars.length;j++){
// 把行号放入rowIDs
rowIDs[i].push(j);
// 把每一行中的内容放入dataBlob对象中
dataBlob[i+':'+j] = cars[j];
}
}
// 更新状态,刷新UI
this.setState({
dataSource:this.state.dataSource.cloneWithRowsAndSections(dataBlob,sectionIDs,rowIDs)
});
},
// 返回cell
renderRow(rowData){
return(
<TouchableOpacity activeOpacity={0.8}>
<View style={styles.rowStyle}>
<Image source={{uri:rowData.icon}} style={styles.rowImageStyle} />
<Text style={styles.rowNameStyle}>{rowData.name}</Text>
</View>
</TouchableOpacity>
);
},
// 返回每一组
renderSectionHeader(sectionData,sectionID){
return(
<View style={styles.sectionHeaderViewStyle}>
<Text style={styles.sectionHeaderTitleStyle}>{sectionData}</Text>
</View>
);
},
// 渲染
render(){
return(
<View style={styles.outerViewStyle}>
<View style={styles.headerViewStyle}>
<Text style={styles.headerTitleStyle}>汽车品牌</Text>
</View>
<ListView
dataSource={this.state.dataSource}
renderRow={this.renderRow}
renderSectionHeader={this.renderSectionHeader}
/>
</View>
);
},
});
const styles = StyleSheet.create({
outerViewStyle:{
// 占满窗口(这样里面的就可以滚动了)
flex:1,
},
headerViewStyle:{
// 导航栏
height:64,
backgroundColor:'orange',
justifyContent:'center', //内部子元素垂直居中
},
headerTitleStyle:{
color:'#fff',
fontSize:25,
textAlign:'center',
},
sectionHeaderViewStyle:{
backgroundColor:'#e8e8e8',
justifyContent:'center',
height:20,
},
sectionHeaderTitleStyle:{
marginLeft:10,
color:'red',
},
rowStyle:{
// 设置水平排列
flexDirection:'row',
// 侧轴方向
alignItems:'center',
padding:10,
borderBottomWidth:0.5,
borderBottomColor:'#e8e8e8',
},
rowImageStyle:{
width:70,
height:70,
},
rowNameStyle:{
marginLeft:10,
},
});
AppRegistry.registerComponent('ListViewDemo3', () => ListViewDemo3);
汽车数据:
{
"data": [
{
"cars": [
{
"icon": "m_180_100.png",
"name": "AC Schnitzer"
},
{
"icon": "m_92_100.png",
"name": "阿尔法·罗密欧"
},
{
"icon": "m_9_100.png",
"name": "奥迪"
},
{
"icon": "m_97_100.png",
"name": "阿斯顿·马丁"
}
],
"title": "A"
},
{
"cars": [
{
"icon": "m_172_100.png",
"name": "巴博斯"
},
{
"icon": "m_157_100.png",
"name": "宝骏"
},
{
"icon": "m_3_100.png",
"name": "宝马"
},
{
"icon": "m_82_100.png",
"name": "保时捷"
},
{
"icon": "m_163_100.png",
"name": "北京汽车"
},
{
"icon": "m_211_100.png",
"name": "北汽幻速"
},
{
"icon": "m_168_100.png",
"name": "北汽威旺"
},
{
"icon": "m_14_100.png",
"name": "北汽制造"
},
{
"icon": "m_2_100.png",
"name": "奔驰"
},
{
"icon": "m_59_100.png",
"name": "奔腾"
},
{
"icon": "m_26_100.png",
"name": "本田"
},
{
"icon": "m_5_100.png",
"name": "标致"
},
{
"icon": "m_127_100.png",
"name": "别克"
},
{
"icon": "m_85_100.png",
"name": "宾利"
},
{
"icon": "m_15_100.png",
"name": "比亚迪"
},
{
"icon": "m_135_100.png",
"name": "布加迪"
}
],
"title": "B"
},
{
"cars": [
{
"icon": "m_129_100.png",
"name": "昌河"
}
],
"title": "C"
},
{
"cars": [
{
"icon": "m_113_100.png",
"name": "道奇"
},
{
"icon": "m_165_100.png",
"name": "大通"
},
{
"icon": "m_8_100.png",
"name": "大众"
},
{
"icon": "m_27_100.png",
"name": "东风"
},
{
"icon": "m_197_100.png",
"name": "东风风度"
},
{
"icon": "m_141_100.png",
"name": "东风风神"
},
{
"icon": "m_115_100.png",
"name": "东风风行"
},
{
"icon": "m_205_100.png",
"name": "东风小康"
},
{
"icon": "m_29_100.png",
"name": "东南"
},
{
"icon": "m_179_100.png",
"name": "DS"
}
],
"title": "D"
},
{
"cars": [
{
"icon": "m_91_100.png",
"name": "法拉利"
},
{
"icon": "m_199_100.png",
"name": "飞驰商务车"
},
{
"icon": "m_164_100.png",
"name": "菲斯克"
},
{
"icon": "m_40_100.png",
"name": "菲亚特"
},
{
"icon": "m_7_100.png",
"name": "丰田"
},
{
"icon": "m_67_100.png",
"name": "福迪"
},
{
"icon": "m_190_100.png",
"name": "弗那萨利"
},
{
"icon": "m_208_100.png",
"name": "福汽启腾"
},
{
"icon": "m_17_100.png",
"name": "福特"
},
{
"icon": "m_128_100.png",
"name": "福田"
}
],
"title": "F"
},
{
"cars": [
{
"icon": "m_109_100.png",
"name": "GMC"
},
{
"icon": "m_110_100.png",
"name": "光冈"
},
{
"icon": "m_147_100.png",
"name": "广汽"
},
{
"icon": "m_63_100.png",
"name": "广汽吉奥"
},
{
"icon": "m_133_100.png",
"name": "广汽日野"
},
{
"icon": "m_182_100.png",
"name": "观致汽车"
}
],
"title": "G"
},
{
"cars": [
{
"icon": "m_31_100.png",
"name": "哈飞"
},
{
"icon": "m_196_100.png",
"name": "哈弗"
},
{
"icon": "m_170_100.png",
"name": "海格"
},
{
"icon": "m_32_100.png",
"name": "海马"
},
{
"icon": "m_149_100.png",
"name": "海马商用车"
},
{
"icon": "m_181_100.png",
"name": "恒天汽车"
},
{
"icon": "m_58_100.png",
"name": "红旗"
},
{
"icon": "m_52_100.png",
"name": "黄海"
},
{
"icon": "m_112_100.png",
"name": "华泰"
},
{
"icon": "m_45_100.png",
"name": "汇众"
}
],
"title": "H"
},
{
"cars": [
{
"icon": "m_35_100.png",
"name": "江淮"
},
{
"icon": "m_37_100.png",
"name": "江铃"
},
{
"icon": "m_38_100.png",
"name": "江南"
},
{
"icon": "m_98_100.png",
"name": "捷豹"
},
{
"icon": "m_143_100.png",
"name": "吉利帝豪"
},
{
"icon": "m_144_100.png",
"name": "吉利全球鹰"
},
{
"icon": "m_148_100.png",
"name": "吉利英伦"
},
{
"icon": "m_39_100.png",
"name": "金杯"
},
{
"icon": "m_57_100.png",
"name": "金龙联合"
},
{
"icon": "m_161_100.png",
"name": "金旅客车"
},
{
"icon": "m_152_100.png",
"name": "九龙"
},
{
"icon": "m_4_100.png",
"name": "Jeep"
}
],
"title": "J"
},
{
"cars": [
{
"icon": "m_188_100.png",
"name": "卡尔森"
},
{
"icon": "m_107_100.png",
"name": "凯迪拉克"
},
{
"icon": "m_150_100.png",
"name": "开瑞"
},
{
"icon": "m_51_100.png",
"name": "克莱斯勒"
},
{
"icon": "m_145_100.png",
"name": "科尼塞克"
},
{
"icon": "m_212_100.png",
"name": "KTM"
}
],
"title": "K"
},
{
"cars": [
{
"icon": "m_86_100.png",
"name": "兰博基尼"
},
{
"icon": "m_200_100.png",
"name": "蓝海房车"
},
{
"icon": "m_80_100.png",
"name": "劳斯莱斯"
},
{
"icon": "m_94_100.png",
"name": "雷克萨斯"
},
{
"icon": "m_99_100.png",
"name": "雷诺"
},
{
"icon": "m_146_100.png",
"name": "莲花"
},
{
"icon": "m_153_100.png",
"name": "猎豹汽车"
},
{
"icon": "m_76_100.png",
"name": "力帆"
},
{
"icon": "m_16_100.png",
"name": "铃木"
},
{
"icon": "m_166_100.png",
"name": "理念"
},
{
"icon": "m_95_100.png",
"name": "林肯"
},
{
"icon": "m_36_100.png",
"name": "陆风"
},
{
"icon": "m_96_100.png",
"name": "路虎"
},
{
"icon": "m_83_100.png",
"name": "路特斯"
}
],
"title": "L"
},
{
"cars": [
{
"icon": "m_183_100.png",
"name": "迈凯伦"
},
{
"icon": "m_93_100.png",
"name": "玛莎拉蒂"
},
{
"icon": "m_18_100.png",
"name": "马自达"
},
{
"icon": "m_79_100.png",
"name": "MG"
},
{
"icon": "m_81_100.png",
"name": "MINI"
},
{
"icon": "m_201_100.png",
"name": "摩根"
}
],
"title": "M"
},
{
"cars": [
{
"icon": "m_155_100.png",
"name": "纳智捷"
}
],
"title": "N"
},
{
"cars": [
{
"icon": "m_104_100.png",
"name": "欧宝"
},
{
"icon": "m_84_100.png",
"name": "讴歌"
},
{
"icon": "m_171_100.png",
"name": "欧朗"
}
],
"title": "O"
},
{
"cars": [
{
"icon": "m_156_100.png",
"name": "启辰"
},
{
"icon": "m_43_100.png",
"name": "庆铃"
},
{
"icon": "m_42_100.png",
"name": "奇瑞"
},
{
"icon": "m_28_100.png",
"name": "起亚"
}
],
"title": "Q"
},
{
"cars": [
{
"icon": "m_30_100.png",
"name": "日产"
},
{
"icon": "m_78_100.png",
"name": "荣威"
},
{
"icon": "m_142_100.png",
"name": "瑞麒"
}
],
"title": "R"
},
{
"cars": [
{
"icon": "m_25_100.png",
"name": "三菱"
},
{
"icon": "m_209_100.png",
"name": "山姆"
},
{
"icon": "m_195_100.png",
"name": "绅宝"
},
{
"icon": "m_50_100.png",
"name": "双环"
},
{
"icon": "m_102_100.png",
"name": "双龙"
},
{
"icon": "m_111_100.png",
"name": "斯巴鲁"
},
{
"icon": "m_10_100.png",
"name": "斯柯达"
},
{
"icon": "m_89_100.png",
"name": "smart"
}
],
"title": "S"
},
{
"cars": [
{
"icon": "m_202_100.png",
"name": "泰卡特"
},
{
"icon": "m_189_100.png",
"name": "特斯拉"
}
],
"title": "T"
},
{
"cars": [
{
"icon": "m_140_100.png",
"name": "威麟"
},
{
"icon": "m_186_100.png",
"name": "威兹曼"
},
{
"icon": "m_19_100.png",
"name": "沃尔沃"
},
{
"icon": "m_48_100.png",
"name": "五菱"
}
],
"title": "W"
},
{
"cars": [
{
"icon": "m_13_100.png",
"name": "现代"
},
{
"icon": "m_174_100.png",
"name": "星客特"
},
{
"icon": "m_71_100.png",
"name": "新凯"
},
{
"icon": "m_87_100.png",
"name": "西雅特"
},
{
"icon": "m_49_100.png",
"name": "雪佛兰"
},
{
"icon": "m_6_100.png",
"name": "雪铁龙"
}
],
"title": "X"
},
{
"cars": [
{
"icon": "m_194_100.png",
"name": "扬州亚星客车"
},
{
"icon": "m_138_100.png",
"name": "野马汽车"
},
{
"icon": "m_100_100.png",
"name": "英菲尼迪"
},
{
"icon": "m_53_100.png",
"name": "一汽"
},
{
"icon": "m_41_100.png",
"name": "依维柯"
},
{
"icon": "m_75_100.png",
"name": "永源"
}
],
"title": "Y"
},
{
"cars": [
{
"icon": "m_136_100.png",
"name": "长安轿车"
},
{
"icon": "m_159_100.png",
"name": "长安商用"
},
{
"icon": "m_21_100.png",
"name": "长城"
},
{
"icon": "m_203_100.png",
"name": "之诺"
},
{
"icon": "m_60_100.png",
"name": "中华"
},
{
"icon": "m_167_100.png",
"name": "中欧"
},
{
"icon": "m_77_100.png",
"name": "众泰"
},
{
"icon": "m_204_100.png",
"name": "中通客车"
},
{
"icon": "m_33_100.png",
"name": "中兴"
}
],
"title": "Z"
}
]
}