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

  1. constructor(props) {
  2. super(props);
  3. var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
  4. this.state = {
  5. dataSource: ds.cloneWithRows(['row 1', 'row 2']),
  6. };
  7. }
  8. render() {
  9. return (
  10. <ListView
  11. dataSource={this.state.dataSource}
  12. renderRow={(rowData) => <Text>{rowData}</Text>}
  13. />
  14. );
  15. }

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

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

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

  1. {
  2. flexDirection: 'row',
  3. flexWrap: 'wrap'
  4. }

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

  1. import React ,{ Component } from 'react';
  2. import {
  3. View,
  4. ListView,
  5. Text,
  6. Image,
  7. TouchableHighlight,
  8. StyleSheet,
  9. Dimensions,
  10. } from 'react-native';
  11. const windowWidth = Dimensions.get('window').width;
  12. var { ListJSON } = require('../JSON/ListJSON'),Utils = require('./Utils');
  13. class ProductInfo extends Component{
  14. constructor(props){
  15. super(props);
  16. }
  17. _gotoBuy(){
  18.  
  19. }
  20. render(){
  21. var product = this.props.product;
  22. return (
  23. <TouchableHighlight onPress={this._gotoBuy} underlayColor={'rgba(0, 0, 0, 0.3)'} style={styles.productWrapper}>
  24. <View style={styles.productDetail}>
  25. <Text style={styles.productDetailTxt}>{product.flowTotalUnit}</Text>
  26. <Text style={styles.productDetailTxt}>/{product.retailPrice / 100}元</Text>
  27. <Text style={styles.productDetailTxt}>{!!product.expiredPrice ? (product.expiredPrice / 100) + '元' : ''}</Text>
  28. </View>
  29. </TouchableHighlight>
  30. );
  31. }
  32. }
  33. class ProductRow extends Component{
  34. constructor(props){
  35. super(props);
  36. }
  37. render(){
  38. return (
  39. <View style={styles.productFlex}>
  40. {
  41. this.props.products.map((item,i) => <ProductInfo product={ item } key = { i }></ProductInfo>)
  42. }
  43. </View>
  44. )
  45. }
  46. }
  47. class List extends Component{
  48. constructor(props){
  49. super(props);
  50. var _getSectionData = (dataBlob, sectionID) => {
  51. return dataBlob[sectionID];
  52. }
  53. var _getRowData = (dataBlob, sectionID, rowID) => {
  54. return dataBlob[sectionID + ':' + rowID];
  55. }
  56. var data = Utils.translateData(ListJSON);
  57. const ds = new ListView.DataSource({
  58. getSectionData: _getSectionData,
  59. getRowData: _getRowData,
  60. rowHasChanged: (row1, row2) => row1 !== row2,
  61. sectionHeaderHasChanged: (s1, s2) => s1 !== s2
  62. });
  63. this.state = {
  64. dataSource: ds.cloneWithRowsAndSections(data.dataBlob, data.sectionIDs, data.rowIDs),
  65. }
  66. }
  67. renderRow(rowData, sectionID, rowID) {
  68. //console.log(rowData,'****')
  69. return (
  70. <ProductRow products={rowData}></ProductRow>
  71. );
  72. }
  73. renderSectionHeader(sectionData, sectionID){
  74. return (
  75. <View>
  76. <Text style={styles.sectionTtl}>{sectionData.scope}{sectionData.type}<Text> | {sectionData.tip}</Text></Text>
  77. </View>
  78. );
  79. }
  80. render(){
  81. return (
  82. <View style={styles.container} >
  83. <ListView dataSource={this.state.dataSource}
  84. contentContainerStyle={styles.listview}
  85. renderRow = {this.renderRow}
  86. renderSectionHeader = {this.renderSectionHeader}
  87. />
  88. </View>
  89. );
  90. }
  91. }
  92. const styles = StyleSheet.create({
  93. container:{
  94. padding:10,
  95. },
  96. listview: {
  97. width:windowWidth-20
  98. },
  99. sectionTtl:{
  100. height:30,
  101. textAlignVertical:'center'
  102. },
  103. productFlex:{
  104. paddingBottom:10,
  105. flexDirection:'row',
  106. justifyContent:'space-between'
  107. },
  108. productWrapper:{
  109. width:(windowWidth-20)*0.485,
  110. borderWidth:1,
  111. borderColor:'#e2e2e2',
  112. borderRadius:4
  113. },
  114. productDetail:{
  115. flexDirection: 'row',
  116. justifyContent:'center'
  117. },
  118. productDetailTxt:{
  119. height:56,
  120. textAlignVertical:'center',
  121. }
  122. });
  123. module.exports = {
  124. List:List
  125. }

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

  1. {
  2. dataBlob: dataBlob,
  3. sectionIDs: sectionIDs,
  4. rowIDs: rowIDs
  5. }

处理section数据方法如下

  1. dataBlob['s'+sectionIdx] = {
  2. "scope": scopev.scopeName,
  3. "type": typeV.typeName,
  4. "tip": tip
  5. }
  6. sectionIDs.push('s'+sectionIdx);
  7. rowIDs[sectionIdx] = [];
  8. var rowIdx = 0;
  9. _.forEach(list, function (item,index) {
  10. let rowAttr = 's'+sectionIdx+':'+rowIdx;
  11. if(index%2==0){
  12. dataBlob[rowAttr] = [];
  13. rowIDs[sectionIdx].push(rowIdx);
  14. }else{
  15. rowIdx++;
  16. }
  17. dataBlob[rowAttr].push(item);
  18. });
  19. 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. asp.net mvc FormsAuthentication一些问题

    form验证最简单的一句 FormsAuthentication.SetAuthCookie(”userName", false); web.config里加上    <machine ...

  2. 更新mac系统和更新到Xcode7.3版本出现的: cannot create __weak reference in file using manual reference counting

    之前的编程没有遇到过,应该是苹果官方那边又做了新规吧. 不过不要紧,只要根据这个就能解决报错问题.  Set Build Settings -> Apple LLVM 7.1 - Languag ...

  3. 如何修改vs2005/vs2010的tfs的登录名和密码 .

    如何修改vs2005/vs2010的tfs的登录名和密码 . 连接TFS时,如果本机保存了用户的网络密码,不会出现用户名和密码的输入框,若要更换TFS的用户名和密码,需按以下步骤操作: 控制面板--- ...

  4. Kotlin——初级篇(三):数据类型详解

    任意一种开发语言都有其数据类型,并且数据类型对于一门开发语言来说是最基本的构成,同时也是最基础的语法.当然,Kotlin也不例外.Kotlin的数据类型和Java是大致相同的,但是他们的写法不同,并且 ...

  5. EasyDSS流媒体服务器软件支持HTTPS-启用https服务申请免费证书

    EasyDSS流媒体服务器软件,提供一站式的转码.点播.直播.时移回放服务,极大地简化了开发和集成的工作. 其中,点播功能主要包含:上传.转码.分发.直播功能,主要包含:直播.录像, 直播支持RTMP ...

  6. 如何理解docker镜像build中的上下文

    参考:https://yeasy.gitbooks.io/docker_practice/content/image/build.html 理解上线文概念非常重要,不然可能碰到一些奇怪的问题. 构建镜 ...

  7. websocket Session 不支持序列化

    这是我本来的打算,把socket session 进行序列化分布式存储! 呵呵   然而现实很残酷,这b东西不支持序列化! 解决办法:

  8. JavaScript和jQuery改变标签内容

    HTML: <div id="mazey">content</div> JavaScript: var mazey=document.getElementB ...

  9. gnu libiconv(可以下载)

    Chinese EUC-CN, HZ, GBK, CP936, GB18030, EUC-TW, BIG5, CP950, BIG5-HKSCS, BIG5-HKSCS:2004, BIG5-HKSC ...

  10. Docker + ElasticSearch + Node.js

    最近有空就想研究下ElasticSearch. 此篇文章用来记录研究过程.备注:需要有一定的docker基础,ElasticSearch的基本概念 Docker安装ElasticSearch 首先,就 ...