React Native常用组件之ListView
1. ListView常用属性
ScrollView 相关属性样式全部继承
dataSource ListViewDataSource 设置ListView的数据源
initialListSize number
设置ListView组件刚刚加载的时候渲染的列表行数,用这个属性确定首屏或者首页加载的数量,而不是花大量的时间渲染加载很多页面数据,提高性能。onChangeVisibleRows function (visibleRows,changedRows)=>void。
当可见的行发生变化的时候回调该方法。onEndReachedThreshold number
当偏移量达到设置的临界值调用onEndReachedonEndReached function
当所有的数据项行被渲染之后,并且列表往下进行滚动。一直滚动到距离底部onEndReachedThredshold设置的值进行回调该方法。原生的滚动事件进行传递(通过参数的形式)。
pageSize number 每一次事件的循环渲染的行数
removeClippedSubviews bool
该属性用于提供大数据列表的滚动性能。该使用的时候需要给每一行(row)的布局添加over:'hidden'样式。该属性默认是开启状态。
renderFooter function 方法 ()=>renderable
在每次渲染过程中头和尾总会重新进行渲染。如果发现该重新绘制的性能开销比较大的时候,可以使用StaticContainer容器或者其他合适的组件。
renderHeader function 方法
在每一次渲染过程中Footer(尾)该会一直在列表的底部,header(头)该会一直在列表的头部,用法同上。
renderRow function (rowData,sectionID,rowID,highlightRow)=>renderable
该方法有四个参数,其中分别为数据源中一条数据,分组的ID,行的ID,以及标记是否是高亮选中的状态信息。renderScrollComponent function
方法 (props)=>renderable 该方法可以返回一个可以滚动的组件。默认该会返回一个ScrollView
renderSectionHeader function (sectionData,sectionID)=>renderable
如果设置了该方法,这样会为每一个section渲染一个粘性的header视图。该视图粘性的效果是当刚刚被渲染开始的时候,该会处于对应的内容的顶部,然后开始滑动的时候,该会跑到屏幕的顶端。直到滑动到下一个section的header(头)视图,然后被替代为止。
renderSeparator function
(sectionID,rowID,adjacentRowHighlighted)=>renderable
如果设置该方法,会在被每一行的下面渲染一个组件作为分隔。除了每一个section分组的头部视图前面的最后一行。scrollRenderAheadDistance number
进行设置当该行进入屏幕多少像素以内之后就开始渲染该行
2. ListView的高阶特性
ListView同样支持一些高级特性,包括设置每一组的粘性的头部(类似于iPhone)、支持设置列表的header以及footer视图、当数据列表滑动到最底部的时候支持onEndReached方法回调、设备屏幕列表可见的视图数据发生变化的时候回调onChangeVisibleRows以及一些性能方面的优化特性。
ListView设计的时候,当需要动态加载非常大的数据的时候,下面有一些方法性能优化的方法可以让我们的ListView滚动的时候更加平滑:
- 只更新渲染数据变化的那一行 ,rowHasChanged方法会告诉ListView组件是否需要重新渲染当前那一行。
- 选择渲染的频率,默认情况下面每一个event-loop(事件循环)只会渲染一行(可以同pageSize自定义属性设置)。这样可以把大的工作量进行分隔,提供整体渲染的性能。
3. Demo1 - ListView的简单使用
3.1 代码
/**
* Sample React Native App
* https://github.com/facebook/react-native
* @flow
*/
import React, {Component} from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
Image,
ListView,
TouchableOpacity,
AlertIOS,
} from 'react-native';
var Dimensions = require('Dimensions');
var {width, height} = Dimensions.get('window');
// 引入数据文件
var models = require("./Wine.json");
var rn0910ListViewTest01 = React.createClass({
/**
* 生命周期,不可更改的属性在这里
* @returns {{}}
*/
getDefaultProps() {
return {}
},
/**
* 生命周期,状态机在这里
* @returns {{}}
*/
getInitialState() {
// 创建数据源 rowHasChanged方法决定了ListView是否重新渲染当前这一行
var ds = new ListView.DataSource({
rowHasChanged: (r1, r2) => {
r1 !== r2
}
});
return {
// 数据源中的数据
dataSource: ds.cloneWithRows(models)
}
},
/**
* 生命周期,复杂的操作在这里
*/
componentDidMount() {
},
/**
* 生命周期,渲染
* @returns {XML}
*/
render() {
return (
<ListView
dataSource={this.state.dataSource} // 指定数据源
renderRow={this.renderRow} // 渲染每一行
/>
);
},
/**
* ListView根据数据源的数据进行渲染
* @param rowData 每一项的数据
* @param sectionID 组号
* @param rowID 行号
* @param highlightRow
* @returns {XML}
*/
renderRow(rowData, sectionID, rowID, highlightRow) {
return (
<TouchableOpacity
activeOpacity={0.7}
onPress={() => this.cellDidClick(rowID, rowData)}
>
<View style={styles.wineCell}>
<Image style={styles.icon} source={{uri: rowData.image}}/>
<View style={styles.titleContainer}>
<Text style={styles.title}>{rowData.name}</Text>
<Text style={styles.subTitle}>${rowData.money}</Text>
</View>
</View>
</TouchableOpacity>
);
},
cellDidClick(rowID, rowData) {
alert("点击了" + rowID + rowData.name);
}
});
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
paddingTop: 20
},
wineCell: {
flexDirection: "row",
borderBottomWidth: 1,
borderBottomColor: '#eee',
paddingLeft: 10,
paddingTop: 10,
paddingBottom: 10,
backgroundColor: 'white'
},
icon: {
width: 60,
height: 60,
},
titleContainer: {
flexDirection: "column",
justifyContent: 'space-between'
},
title: {
fontSize: 15,
fontWeight: 'bold',
width: width - 60,
paddingLeft: 10,
paddingRight: 10
},
subTitle: {
fontSize: 15,
marginLeft: 10,
}
});
AppRegistry.registerComponent('rn0910ListViewTest01', () => rn0910ListViewTest01);
3.2 效果图
4. ListView之九宫格布局
listViewContentStyle: {
// ListView实现九宫格布局,主要是这俩属性
flexDirection: 'row',
flexWrap: 'wrap'
},
cellStyle: {
alignItems: 'center',
// 每一项设置宽高
width: cellWH,
height: cellWH,
marginLeft: hMargin,
marginTop: tMargin
},
4.1 代码
/**
* Sample React Native App
* https://github.com/facebook/react-native
* @flow
*/
import React, {Component} from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
ListView,
Image,
TouchableOpacity,
AlertIOS
} from 'react-native';
// 引入json文件
var models = require("./shareData.json");
// 获取屏幕宽度
var Dimensions = require('Dimensions');
var screen_Width = Dimensions.get('window').width;
var col = 3; // 列数
var cellWH = 100; // 每项宽高
var tMargin = 25; // 行 顶间距
var hMargin = (screen_Width - cellWH * col) / (col + 1); // 每项之间的间距
var rn0912ListViewTest02 = React.createClass({
/**
* 不可修改的属性
* @returns {{}}
*/
getDefaultProps() {
return {}
},
/**
* 状态机
*/
getInitialState() {
var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
return {
dataSource: ds.cloneWithRows(models.data)
}
},
/**
* 渲染
* @returns {{}}
*/
render() {
return (
<ListView
dataSource={this.state.dataSource}
renderRow={this.renderRow}
contentContainerStyle={styles.listViewContentStyle}
/>
)
},
/**
* 操作
*/
componentDidMount() {
},
renderRow(rowData) {
return (
<TouchableOpacity
activeOpacity={0.8}
onPress={() => {
alert("点击分享到" + rowData.title)
}}
>
<View style={styles.cellStyle}>
<Image style={styles.iconStyle} source={{uri: rowData.icon}}/>
<Text style={styles.nameStyle}>{rowData.title}</Text>
</View>
</TouchableOpacity>
);
}
});
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
listViewContentStyle: {
// ListView实现九宫格布局,主要是这俩属性
flexDirection: 'row',
flexWrap: 'wrap'
},
cellStyle: {
alignItems: 'center',
// 每一项设置宽高
width: cellWH,
height: cellWH,
marginLeft: hMargin,
marginTop: tMargin
},
iconStyle: {
width: 80,
height: 80,
},
nameStyle: {
fontSize: 14
}
});
AppRegistry.registerComponent('rn0912ListViewTest02', () => rn0912ListViewTest02);
4.2 效果图
5. ListView黏性sectionHeader
5.1 技术点分析
如何实现滚动时每个sectionHeader会吸顶?
在ListView中要实现sticky,需要使用cloneWithRowsAndSections方法,将dataBlob(object),sectionIDs(array),rowIDs(array)三个值传进去.
dataBlob
dataBlob包含ListView所需的所有的数据(sectionHeader 和 rows),在ListView渲染数据时,使用getSectionData 和 getRowData 来渲染每一行数据. dataBlob的 key 值包含sectionID + rowID
sectionIDs
sectionIDs 用语表示每组section
rowIDs 二维数组
rowIDs 用于描述每个section里的每行数据的位置及是否需要渲染. 在ListView渲染时,会先遍历 rowIDs 获取到对应的 dataBlob 数据
模拟对应的数据结构
在 DataSource 中, 设置ListView获取 row 和 section 的方法
getInitialState() {
var getSectionHeaderData = (dataBlob, sectionID) => {
return dataBlob[sectionID];
}
var getRowData = (dataBlob, sectionID, rowID) => {
return dataBlob[sectionID + ":" + rowID];
}
return {
// 设置数据源,数据庞大,在
dataSource: new ListView.DataSource({
getSectionHeaderData: getSectionHeaderData, // 获取组数据
getRowData: getRowData, // 获取行数据
rowHasChanged: (r1, r2) => {
r1 !== r2
}, // 什么时候创建行
sectionHeaderHasChanged: (s1, s2) => {
s1 !== s2
} // 什么时候创建组
})
};
},
刷新状态机,将数据传入到ListView中
this.setState({
dataSource: this.state.dataSource.cloneWithRowsAndSections(dataBlob, sectionIDs, rowIDs)
});
ListView中不仅要renderRow 还要 renderSectionHeader
<ListView
dataSource={this.state.dataSource}
renderRow={this.renderRow}
renderSectionHeader={this.renderSectionHeader}
/>
5.2 代码
/**
* 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';
var carData = require("./Car.json");
var rn0913ListViewTest03 = React.createClass({
/**
* 不可更改的属性
* @returns {{}}
*/
getDefaultProps() {
return {};
},
/**
* 状态机
* @returns {{}}
*/
getInitialState() {
var getSectionHeaderData = (dataBlob, sectionID) => {
return dataBlob[sectionID];
}
var getRowData = (dataBlob, sectionID, rowID) => {
return dataBlob[sectionID + ":" + rowID];
}
return {
// 这里就没有指定数据源,由于需要处理数据,所以在componentDidMount()方法中进行数据处理
dataSource: new ListView.DataSource({
getSectionHeaderData: getSectionHeaderData, // 获取组数据
getRowData: getRowData, // 获取行数据
rowHasChanged: (r1, r2) => {
r1 !== r2
}, // 什么时候创建行
sectionHeaderHasChanged: (s1, s2) => {
s1 !== s2
} // 什么时候创建组
})
};
},
/**
* 渲染界面
*/
render() {
return (
<View style={styles.container}>
<View style={styles.nav}>
<Text style={styles.navTitle}>Chaos车库</Text>
</View>
<ListView
dataSource={this.state.dataSource}
renderRow={this.renderRow}
renderSectionHeader={this.renderSectionHeader}
/>
</View>
);
},
/**
* 渲染每一项
* @param rowData
* @returns {XML}
*/
renderRow(rowData) {
return (
<TouchableOpacity activeOpacity={0.8}>
<View style={styles.cellStyle}>
<Image style={styles.imgStyle} source={{uri: rowData.icon}}/>
<Text style={styles.carTitleStyle}>{rowData.name}</Text>
</View>
</TouchableOpacity>
);
},
/**
* 渲染每一组
* @param sectionData
* @returns {XML}
*/
renderSectionHeader(sectionData) {
return (
<TouchableOpacity activeOpacity={0.8}>
<View style={styles.headerStyle}>
<Text style={styles.headerTextStyle}>{sectionData}</Text>
</View>
</TouchableOpacity>
);
},
/**
* 复杂操作
*/
componentDidMount() {
this.loadDataFromJson();
},
/**
* 加载数据,处理数据
*/
loadDataFromJson() {
var jsonData = carData.data;
var dataBlob = {}, // 对象
sectionIDs = [],
rowIDs = [], // 这是个二维数组
cars = [];
for (var i = 0; i < jsonData.length; i++) {
// 确定每组的id
sectionIDs.push(i);
// 确定每组的id对应的组数据
dataBlob[i] = jsonData[i].title;
// 获取行集合
cars = jsonData[i].cars;
rowIDs[i] = []; // 二维数组,每一项都是行id的数组
for (var j = 0; j < cars.length; j++) {
rowIDs[i].push(j);
// 确定每一行的数据
dataBlob[i + ":" + j] = cars[j];
}
}
// 给ListView的数据源赋值
this.setState({
dataSource: this.state.dataSource.cloneWithRowsAndSections(dataBlob, sectionIDs, rowIDs)
});
}
});
const styles = StyleSheet.create({
container: {},
nav: {
height: 64,
backgroundColor: '#eee',
alignItems: 'center',
justifyContent: 'center'
},
navTitle: {
fontSize:26
},
headerStyle: {
backgroundColor: '#ccc',
height:30,
},
headerTextStyle: {
lineHeight:30,
paddingLeft:10
},
cellStyle: {
borderBottomColor:'#eee',
borderBottomWidth:0.5,
flexDirection:'row',
alignItems:'center',
padding:10
},
imgStyle: {
width: 60,
height: 60
},
carTitleStyle: {
marginLeft:10
}
});
AppRegistry.registerComponent('rn0913ListViewTest03', () => rn0913ListViewTest03);
5.3 效果图
React Native常用组件之ListView的更多相关文章
- React Native常用组件之ListView组件
学习iOS开发的同学应该都知道UITableView,几乎每个APP中都有它的存在,而且衍生出各种形态:那么同样,ListView就是在React Native中的tableView,而且更加简单和灵 ...
- React Native常用组件在Android和IOS上的不同
React Native常用组件在Android和IOS上的不同 一.Text组件在两个平台上的不同表现 1.1 height与fontSize 1.1.1只指定font,不指定height 在这种情 ...
- react native 常用组件汇总
react-native-uploader //文件上传https://github.com/aroth/react-native-uploader jpush-react-native //官方版本 ...
- React Native常用组件之ScrollView
1. 两个要点 1.1 ScrollView必须有一个确定的高度才能正常工作 它实际上所做的就是将一系列不确定高度的子组件装进一个确定高度的容器(通过滚动操作) 通常有两种做法: 第一种: 直接给该S ...
- React Native常用组件之ScrollView组件
一.前言 从iOS开发的经验来看,scrollView无疑是移动开发中很重要的一个组件,比如后面会学到的ListView就是继承自它.那么,在开发中比如:焦点图.引导页等地方都有其的影子,那接下来我们 ...
- React Native常用组件Image使用
前言 学习本系列内容需要具备一定 HTML 开发基础,没有基础的朋友可以先转至 HTML快速入门(一) 学习 本人接触 React Native 时间并不是特别长,所以对其中的内容和性质了解可能会有所 ...
- 一起来点React Native——常用组件之Touchable系列
在前面的登录界面中,我们发现所有的组件不会对用户的点击.触摸.拖拽做出合适的响应,这是十分不友好的.那么,在React Native中如何让视图对触发做出合适的响应呢? 一.高亮触摸 Touchab ...
- React Native常用组件之TabBarIOS、TabBarIOS.Item组件、Navigator组件、NavigatorIOS组件、React Navigation第三方
以下内容为老版本React Native,faceBook已经有了新的导航组件,请移步其他博客参考>>[我是传送门] 参考资料:React Navigation react-native ...
- 一起来点React Native——常用组件之Image
一.前言 在开发中还有一个非常重要的组件Image,通过这个组件可以展示各种各样的图片,而且在React Native中该组件可以通过多种方式加载图片资源. 二.Image组件的基本用法 2.1 从当 ...
随机推荐
- BZOJ.4825.[AHOI/HNOI2017]单旋(线段树)
BZOJ LOJ 洛谷 这题不难啊,我怎么就那么傻,拿随便一个节点去模拟.. 我们只需要能够维护,将最小值或最大值转到根.模拟一下发现,对于最小值,它的右子树深度不变(如果存在),其余节点深度全部\( ...
- JavaScript基础笔记(十二)Ajax
Ajax 一.XMLHttpRequest对象 一)XHR用法 var xhr = new XMLHttpRequest(); //open()方法,参数一:发送方法,参数二:请求的URL,参数三:是 ...
- CY7C68013 USB接口相机开发记录 - 第四天:上位机编写1
前面学习了USB相机硬件固件.设备驱动,可以实现USB设备识别.数据发送的功能.然后,非常重要的一部分,USB设备发出的数据,我要怎么接受,怎么查看发送的数据是否是正确的.网上百度了下,大部分人都使用 ...
- 利用select检索数据
没错这就是DQL,数据查询语言.来看看怎么用. select语句按照复杂程度来说分为简单查询.where查询.多表查询.子查询等. 先来看看select的语法 1.select 2.[distince ...
- BZOJ4267 : 小强的颜色
首先剔除$1$号心情不能到达的无用心情,然后采用分割法进行DFA的最小化. 每次遍历所有集合,将集合中和集合中第一个心情行为或者转移所在集合不同的心情放入新集合中. 最后按字典序依次给每个集合编号即可 ...
- Expedition [POJ2431] [贪心]
题目大意: 有n个加油站,每个加油站的加油的油量有限,距离终点都有一个距离. 一个卡车的油箱无限,每走一个单元要消耗一单元的油,问卡车到达终点的最少加多少次油. 分析: 我们希望的是走到没油的时候就尽 ...
- C# 计算地图上某个坐标点的是否在多边形内
这个方法引用自群友的博客 https://www.xiaofengyu.com/?p=143 使用百度地图的时候,常常会用到判断一个点是否在一个多边形的范围内,该方法用到的是射线法, 通过修改Java ...
- 小甲鱼Python第十六讲课后习题--017函数
函数的定义用def,函数名后要用冒号 函数的返回:函数中使用return 测试题: 0. 你有听说过DRY吗? DRY是指Don't Repeat Yourself ,特指在程序设计以及计算中避免 ...
- python之类和对象
对象(object)基本上可以看做数据(特性)以及由一系列可以存取.操作这些数据的方法所组成的集合. 类,可以看成种类,类型,从一组对象中提取到的相似部分.所有的对象都属于一个类,称为类的实例. 之前 ...
- GMA Round 1 年货
传送门 年货 三角形的年货有没有见过啊?(如下图所示,图中共有12层小三角形,共计144个) 啊,不,这不是真正的年货,真正的年货是正六边形的!(这是什么设定?) 总之,麻烦你在图中找出顶点在三角形格 ...