本系列是基于React Native
版本号0.44.3
写的。几乎所有的App都使用了ListView
这种组件,这篇文章将学习RN
中ListView
的平铺样式和分组样式。
ListView
内部是通过ListViewDataSource
这个对象显示数据的,因此使用ListView
的时候需要创建一个ListViewDataSource
对象。ListViewDataSource
构造方法创建对象的时候可以选择性出入4个参数,描述怎么提取cell,怎么刷新cellListViewDataSource
为ListView
组件提供高性能的数据处理和访问。我们需要调用clone
方法从原始输入数据中抽取数据来创建ListViewDataSource
对象。datasource
中的数据,请(每次都重新)调用cloneWithRows
方法(如果用到了section
,则对应cloneWithRowsAndSections
方法)clone
方法会自动提取新数据并进行逐行对比(使用rowHasChanged
方法中的策略),这样ListView
就知道哪些行需要重新渲染了。setState
ListViewDataSource
使用ListView.DataSource
ListViewDataSource
构造方法:决定ListView
怎么去处理数据,需要传入一个对象,这个对象有四个可选属性,都是方法。ListViewDataSource
的时候,如果不需要修改提取数据的方式,只需要实现rowHasChanged
,告诉什么时候刷新下一行ListViewDataSource
有提取数据方式,可以使用默认提取方式。2.给数据源设置数据
3.实现数据源方法,确定cell
运行上面的代码,你会发现ListView
没有分割线,我们可以添加分割线:
render() {
return (
<ListView style={{marginTop: 20}}
dataSource={this.state.dataSource}
renderRow={this._renderRow.bind(this)}
renderSeparator={this._renderSeparator.bind(this)}
/>
);
}
_renderSeparator(sectionID, rowID, adjacentRowHighlighted) {
return (
<View style={{height:1,backgroundColor:'black'}}>
</View>
)
}
_renderHeader(){
return (
<View style={[{height:30}, {backgroundColor:'red'},{justifyContent: 'center'}]}>
<Text style={[{textAlign: 'center'}]}>头部视图</Text>
</View>
);
}
效果图:
_renderFooter(){
return (
<View style={[{height: 30}, {backgroundColor: 'red'}, {justifyContent:'center'}]}>
<Text style={{textAlign: `center`}}>尾部视图</Text>
</View>
)
}
效果图:
_renderRow(rowData, sectionID, rowID, highlightRow){
return (
<TouchableOpacity onPress={()=>{
AlertIOS.alert(rowID)
highlightRow(sectionID, rowID)
}}>
<View style={{height: 40}}>
<Text>{rowData}</Text>
</View>
</TouchableOpacity>
);
}
注意:需要导入TouchableOpacity
和AlertIOS
有时候我们会遇到ListView
分组样式,比如中国有多少个省,然后每个省又有多少个城市。
要想明白ListView
是如何分组的,就需要知道ListView
底层是如何获取组数据,行数据。
ListView
默认支持3种格式的数据,只要按照这3种格式处理数据,就会自动获取数据,从而达到分组样式默认的3种格式的数据:
// 格式一
[[row_0, row_1,...],[row_0, row_1,...],...]
// 格式二
{sectionID_0:{rowID_0, rowID_1, rowID_2, ...}, ...}
// 格式三
{sectionID_0:[rowID_0, rowID_1, ...], ...}
cloneWithRows()
cloneWithRowsAndSections()
this.state = { dataSource: ds.cloneWithRowsAndSections(Data) }
ListView
这个例子我们使用了本地假数据,创建一个Data.json
文件,它看起来是这样:
[
["section0-row0","section0-row1","section0-row2","section0-row3"],
["section1-row0","section1-row1","section1-row2","section1-row3"],
["section2-row0","section2-row1","section2-row2","section2-row3"],
["section3-row0","section3-row1","section3-row2","section3-row3"],
["section4-row0","section4-row1","section4-row2","section4-row3"],
["section5-row0","section5-row1","section5-row2","section5-row3"]
]
我们在index.ios.js
里面引用Data.json
var Data = require('./Data.json')
然后就按照上述 实现ListView
分组样式 步骤写:
var Data = require('./Data.json')
// 主组件
export default class RNDemoOne extends Component {
// 构造
constructor(props) {
super(props);
// 初始状态
var ds = new ListView.DataSource({
rowHasChanged: (r1, r2) => r1 !== r2,
sectionHeaderHasChanged: (s1, s2) => s1 !== s2
});
this.state = {
dataSource: ds.cloneWithRowsAndSections(Data)
}
}
render() {
return (
<ListView style={{marginTop: 20}}
dataSource={this.state.dataSource}
renderRow={this._renderRow.bind(this)}
renderSeparator={this._renderSeparator.bind(this)} renderSectionHeader={this._renderSectionHeader.bind(this)}
/>
);
}
_renderSectionHeader(sectionData, sectionID){
return (
<View style={[{height: 40}, {backgroundColor:'red'}]}>
<View style={[{flex:1}, {justifyContent: 'center'}]}>
<Text style={{paddingLeft: 10}}>{sectionID}</Text>
</View>
</View>
)
}
_renderRow(rowData, sectionID, rowID, highlightRow){
return (
<TouchableOpacity onPress={()=>{
AlertIOS.alert(rowID)
highlightRow(sectionID, rowID)
}}>
<View style={{height: 40}}>
<Text>{rowData}</Text>
</View>
</TouchableOpacity>
);
}
_renderSeparator(sectionID, rowID, adjacentRowHighlighted) {
return (
<View style={{height:1,backgroundColor:'black'}}>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
});
如果发现有错误的地方,欢迎各位指出,谢谢!