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++;

  

  

React-Native Listview组件用法详解的更多相关文章

  1. React Native的组件ListView

    React Native的组件ListView类似于iOS中的UITableView和UICollectionView,也就是说React Native的组件ListView既可以实现UITableV ...

  2. JSON详解+ C# String.Format格式说明+ C# ListView用法详解 很完整

    JSON详解 C# String.Format格式说明 C# ListView用法详解 很完整

  3. 中间件:ElasticSearch组件RestHighLevelClient用法详解

    本文源码:GitHub·点这里 || GitEE·点这里 一.基础API简介 1.RestHighLevelClient RestHighLevelClient的API作为ElasticSearch备 ...

  4. Vue1.0用法详解

    Vue.js 不支持 IE8 及其以下版本,因为 Vue.js 使用了 IE8 不能实现的 ECMAScript 5 特性. 开发环境部署 可参考使用 vue+webpack. 基本用法 1 2 3 ...

  5. Elasticsearch SQL用法详解

    Elasticsearch SQL用法详解  mp.weixin.qq.com 本文详细介绍了不同版本中Elasticsearch SQL的使用方法,总结了实际中常用的方法和操作,并给出了几个具体例子 ...

  6. Vue props用法详解

    Vue props用法详解 组件接受的选项之一 props 是 Vue 中非常重要的一个选项.父子组件的关系可以总结为: props down, events up 父组件通过 props 向下传递数 ...

  7. Vue插件编写、用法详解(附demo)

    Vue插件编写.用法详解(附demo) 1.概述 简单来说,插件就是指对Vue的功能的增强或补充. 比如说,让你在每个单页面的组件里,都可以调用某个方法,或者共享使用某个变量,或者在某个方法之前执行一 ...

  8. react第五单元(事件系统-原生事件-react中的合成事件-详解事件的冒泡和捕获机制)

    第五单元(事件系统-原生事件-react中的合成事件-详解事件的冒泡和捕获机制) 课程目标 深入理解和掌握事件的冒泡及捕获机制 理解react中的合成事件的本质 在react组件中合理的使用原生事件 ...

  9. React源码 commit阶段详解

    转: React源码 commit阶段详解 点击进入React源码调试仓库. 当render阶段完成后,意味着在内存中构建的workInProgress树所有更新工作已经完成,这包括树中fiber节点 ...

随机推荐

  1. 有向图 加最少的边 成为强连通分量的证明 poj 1236 hdu 2767

    poj 1236: 题目大意:给出一个有向图, 任务一: 求最少的点,使得从这些点出发可以遍历整张图  任务二: 求最少加多少边 使整个图变成一个强连通分量. 首先任务一很好做, 只要缩点 之后 求 ...

  2. apache2+svn Cannot load modules/mod_dav_svn.so into server: \xd5\xd2\xb2\xbb\xb5\xbd\xd6\xb8\xb6\xa8\xb5\xc4\xc4\xa3\xbf\xe9\xa1\xa3

    按照svn里的readme文件安装配置apache2与svn后, 启动apache2服务的时候 出现下面的问题 Cannot load C:/Program Files/Apache Software ...

  3. Unity3D学习笔记——Android重力感应控制小球

    一:准备资源 两张贴图:地图和小球贴图. 二:导入资源 在Assets下建立resources文件夹,然后将贴图导入. 三:建立场景游戏对象 1.建立灯光: 2.创建一个相机,配置默认. 3.建立一个 ...

  4. JNI动态库生成、编译、查看相关简易资料

    有一篇好博文,大家可以看下http://www.cnblogs.com/zhangweia/archive/2010/09/16/1828176.html,我这里是参考其做的另外一个javah -cl ...

  5. sedna进行xquery查询

    有一个文件book.xml: <books> <book> <name>The Call Of Wild</name> <author>Ja ...

  6. 4、easyUI-七种布局(layout)

    1.为网页创建边框布局 边框布局(border layout)提供五个区域:east.west.north.south.center.以下是一些通常用法: north 区域可以用来显示网站的标语. s ...

  7. html5离线缓存使用

    html5 离线缓存使用以及注意事项 1.index.html中加入离线缓存的声明文件 如:<!DOCTYPE html><html manifest="test.appc ...

  8. Handler classes should be static or leaks might occur

    http://droidyue.com/blog/2014/12/28/in-android-handler-classes-should-be-static-or-leaks-might-occur ...

  9. 1076: [SCOI2008]奖励关

    1076: [SCOI2008]奖励关 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2078  Solved: 1118[Submit][Statu ...

  10. javascript数组遍历for与for in区别详解

    js中遍历数组的有两种方式 复制代码代码如下: var array=['a']//标准的for循环for(var i=1;i<array.length;i++){    alert(array[ ...