ListView作为React Native的核心组件,用于高效地显示一个可以垂直滚动的变化的数据列表。其中最重要的属性之一是DataSource,列表依赖的数据源,用于实例化一个ListView对象。此外ListView可以使用所有ScrollView的属性。一个最简单的例子:

constructor(props) {
super(props);
var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.state = {
dataSource: ds.cloneWithRows(['row 1', 'row 2']),
};
}
render() {
return (
<ListView
dataSource={this.state.dataSource}
renderRow={(rowData) => <Text>{rowData}</Text>}
/>
);
}

然而实际开发中往往遇到更复杂的需求,本文将介绍如何使用ListView一些高级特性解决难题。

需求描述:实现一个分组商品列表,最终陈列效果为多行多列。具体如图标红区域。

需求拆分:ListView Section,每一块(Section)包含标题+内容。渲染块标题的函数为renderSectionHeader;渲染条目数据的函数为renderRow。难点在于每一行显示两条数据,ListView contentContainerStyle属性赋值为如下对象,出现只能显示一行的bug,不分组的ListView不会出现这个问题。

{
flexDirection: 'row',
flexWrap: 'wrap'
}

最终解决方案:在ListView 和单条目数据Row之间,插入一个组件,该组件数据源为行数据(长度为2或者1的数组),以此实现多行多列。也就是说renderRow函数从渲染单条目数据,转为渲染一行所需的数据。

import React ,{ Component } from 'react';
import {
View,
ListView,
Text,
Image,
TouchableHighlight,
StyleSheet,
Dimensions,
} from 'react-native';
const windowWidth = Dimensions.get('window').width;
var { ListJSON } = require('../JSON/ListJSON'),Utils = require('./Utils');
class ProductInfo extends Component{
constructor(props){
super(props);
}
_gotoBuy(){ }
render(){
var product = this.props.product;
return (
<TouchableHighlight onPress={this._gotoBuy} underlayColor={'rgba(0, 0, 0, 0.3)'} style={styles.productWrapper}>
<View style={styles.productDetail}>
<Text style={styles.productDetailTxt}>{product.flowTotalUnit}</Text>
<Text style={styles.productDetailTxt}>/{product.retailPrice / 100}元</Text>
<Text style={styles.productDetailTxt}>{!!product.expiredPrice ? (product.expiredPrice / 100) + '元' : ''}</Text>
</View>
</TouchableHighlight>
);
}
}
class ProductRow extends Component{
constructor(props){
super(props);
}
render(){
return (
<View style={styles.productFlex}>
{
this.props.products.map((item,i) => <ProductInfo product={ item } key = { i }></ProductInfo>)
}
</View>
)
}
}
class List extends Component{
constructor(props){
super(props);
var _getSectionData = (dataBlob, sectionID) => {
return dataBlob[sectionID];
}
var _getRowData = (dataBlob, sectionID, rowID) => {
return dataBlob[sectionID + ':' + rowID];
}
var data = Utils.translateData(ListJSON);
const ds = new ListView.DataSource({
getSectionData: _getSectionData,
getRowData: _getRowData,
rowHasChanged: (row1, row2) => row1 !== row2,
sectionHeaderHasChanged: (s1, s2) => s1 !== s2
});
this.state = {
dataSource: ds.cloneWithRowsAndSections(data.dataBlob, data.sectionIDs, data.rowIDs),
}
}
renderRow(rowData, sectionID, rowID) {
//console.log(rowData,'****')
return (
<ProductRow products={rowData}></ProductRow>
);
}
renderSectionHeader(sectionData, sectionID){
return (
<View>
<Text style={styles.sectionTtl}>{sectionData.scope}{sectionData.type}<Text> | {sectionData.tip}</Text></Text>
</View>
);
}
render(){
return (
<View style={styles.container} >
<ListView dataSource={this.state.dataSource}
contentContainerStyle={styles.listview}
renderRow = {this.renderRow}
renderSectionHeader = {this.renderSectionHeader}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container:{
padding:10,
},
listview: {
width:windowWidth-20
},
sectionTtl:{
height:30,
textAlignVertical:'center'
},
productFlex:{
paddingBottom:10,
flexDirection:'row',
justifyContent:'space-between'
},
productWrapper:{
width:(windowWidth-20)*0.485,
borderWidth:1,
borderColor:'#e2e2e2',
borderRadius:4
},
productDetail:{
flexDirection: 'row',
justifyContent:'center'
},
productDetailTxt:{
height:56,
textAlignVertical:'center',
}
});
module.exports = {
List:List
}

分组列表需要的数据格式如下:

{
dataBlob: dataBlob,
sectionIDs: sectionIDs,
rowIDs: rowIDs
}

处理section数据方法如下

dataBlob['s'+sectionIdx] = {
"scope": scopev.scopeName,
"type": typeV.typeName,
"tip": tip
}
sectionIDs.push('s'+sectionIdx);
rowIDs[sectionIdx] = [];
var rowIdx = 0;
_.forEach(list, function (item,index) {
let rowAttr = 's'+sectionIdx+':'+rowIdx;
if(index%2==0){
dataBlob[rowAttr] = [];
rowIDs[sectionIdx].push(rowIdx);
}else{
rowIdx++;
}
dataBlob[rowAttr].push(item);
});
sectionIdx++;

  

  

最新文章

  1. CentOS 7.0 部署 Django 到运行起来第一个web service
  2. scala基础语法(变量,数据类型,函数)
  3. STAF自动化测试框架
  4. ops中set_sysclk set_clkdiv set_pll详解
  5. android 完美退出所有Activity的demo
  6. gtest功能测试一
  7. Android Studio怎么删除项目
  8. android 休眠唤醒机制分析(三) — suspend
  9. CSS Font-family常用设置
  10. CSS3的使用方法解析
  11. SoapUI进行接口测试,怎么应对接口地址总是变化!
  12. 第三方推送 JPush 配置中的引入so库问题
  13. [LeetCode] Maximum Width of Binary Tree 二叉树的最大宽度
  14. win10 音频设备图形隔离 占用CPU
  15. Q&amp;A in Power BI service and Power BI Desktop
  16. VUE项目 npm run build卡住不动,也不报错
  17. SQL语句方法语法总结(一)
  18. Linux程序设计:进程通信
  19. mongoDB进行分组操作
  20. javascript 链式写法

热门文章

  1. libsvm以概率输出单个test样例的判别结果
  2. iOS --转载2018苹果$299美元企业级开发者账号申请攻略
  3. 输入一个十进制数N,将它转换成R进制数输出(运用递归实现)
  4. caffe小问题汇总(持续更新)
  5. MySQL基本操作(+参考手册)
  6. Django项目部署(django+guncorn+virtualenv+nginx)
  7. SpringMVC 资源国际化实现以及常见问题
  8. eval()和exec()函数的区别
  9. window.XMLHttpRequest对象详解
  10. 【转】mysql利用init-connect增加访问审计功能