1.import添加listview的引用
import {
StyleSheet,
View,
Text,
Navigator,
ListView,
Image,
TouchableOpacity,
ActivityIndicator,
RefreshControl,
} from 'react-native';
2.ListView的使用
ListView组件必须的两个属性是dataSource和renderRow。dataSource是列表的数据源,而renderRow则逐个解析数据源中的数据,然后返回一个设定好格式的组件来渲染。
在render()中,我们渲染一个ListView,在ListView的属性中,我们指定了dataSource和renderRow,这两个属性分别代表ListView的数据源和渲染的每一行。
dataSource
如果我们要创建一个数据源,最基本的方法就是创建一个ListView.DataSource数据源,然后通过cloneWithRows方法为其传递一个数组。
其中提供给数据源的rowHasChanged函数可以告诉ListView它是否需要重绘一行数据,即数据是否发生了改变,即在需要重绘界面的时候会进行判断,如果之前页面中的改行数据没有发生变化,则不再进行重绘,否则进行重绘。
renderRow
(rowData, sectionID, rowID, highlightRow) => renderable
该属性需要传入一个方法,该方法如上所示,他会从数据源中接受一条数据,以及他和他所在的section的Id,返回一个可渲染的组件来为这行数据进行渲染,默认情况下参数中的数据就是放进数据源中的数据本身,不过也可以提供一些转换器。
3.其他属性
initialListSize number :
指定在组件刚挂载的时候渲染多少行数据。用这个属性来确保首屏显示合适数量的数据,而不是花费太多帧逐步显示出来。
onChangeVisibleRows function: (visibleRows, changedRows) => void
当可见的行的集合变化的时候调用此回调函数。visibleRows 以 { sectionID: { rowID: true }}的格式包含了所有可见行,而changedRows 以{ sectionID: { rowID: true | false }}的格式包含了所有刚刚改变了可见性的行,其中如果值为true表示一个行变得可见,而为false表示行刚刚离开可视区域而变得不可见。
pageSize number :
每次事件循环(每帧)渲染的行数。
renderRow function (rowData, sectionID, rowID, highlightRow) => renderable
从数据源(Data source)中接受一条数据,以及它和它所在section的ID。返回一个可渲染的组件来为这行数据进行渲染。默认情况下参数中的数据就是放进数据源中的数据本身,不过也可以提供一些转换器。
如果某一行正在被高亮(通过调用highlightRow函数),ListView会得到相应的通知。当一行被高亮时,其两侧的分割线会被隐藏。行的高亮状态可以通过调用highlightRow(null)来重置。
下面直接贴上Demo代码
首先是目录结构
项目目录结构service.js
/*
* 服务URL
*/
module.exports = {
//电影搜索
movie_search: 'https://api.douban.com/v2/movie/search',
};
Utils.js
import React, { Component } from 'react';
/*!
*
* Util模块 React Native module
* 主要提供工具方法
*
*/
import Dimensions from 'Dimensions';
import {
PixelRatio,
ActivityIndicator
} from 'react-native';
module.exports = {
navigationHeight: 44,
navigationBarBGColor:'#3497FF',
statusBarHeight: 20,
/*最小线宽*/
pixel: 1 / PixelRatio.get(),
/*屏幕尺寸*/
size: {
width: Dimensions.get('window').width,
height: Dimensions.get('window').height
},
/**
* 基于fetch的get方法
* @method post
* @param {string} url
* @param {function} callback 请求成功回调
*/
get: function(url, successCallback,failCallback){
fetch(url)
.then((response) => response.text())
.then((responseText) => {
successCallback(JSON.parse(responseText));
})
.catch(function(err){
failCallback(err);
});
},
/*loading效果*/
loading: <ActivityIndicator animating={true} color="#3E00FF" style={{marginTop:Dimensions.get('window').height/2-50,alignItems: 'center',
justifyContent: 'center'}} size="large"/>
};
infoListView.js
'use strict'
import React, { Component } from 'react';
import Util from './common/util' ;
import ServiceURL from './common/service' ;
import {
StyleSheet,
View,
Text,
Navigator,
ListView,
Image,
TouchableOpacity,
ActivityIndicator,
RefreshControl,
} from 'react-native';
export default class Sample_InfoListView extends Component{
constructor(props) {
super(props);
var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.state = {
dataSource: ds.cloneWithRows([]),
keywords: 'BBC',
show: false,
isRefreshing: false,
}
}
render(){
return(
<View style={[styles.flex_1,{marginBottom:10}]}>
{
this.state.show ?
<ListView
dataSource={this.state.dataSource}
renderRow={this._renderRow}
enableEmptySections={true}
refreshControl={
<RefreshControl
refreshing={this.state.isRefreshing}
onRefresh={()=>{
this.setState({isRefreshing: true});
setTimeout(() => {
this.setState({
isRefreshing: false,
});
}, 3000);}}
tintColor="black"
title="Loading..."
titleColor="black"
colors={['#ff0000', '#00ff00', '#0000ff']}
progressBackgroundColor="#ffff00"
/>
}/>
: Util.loading
}
</View>
);
}
componentDidMount(){
this._getData();
}
_changeText(val){
this.setState({
keywords: val
});
}
_renderRow(row){
var casts = row.casts;
var names = [];
for(var i in casts){
names.push(casts[i].name);
}
return (
<View style={[styles.row,styles.item]}>
<View>
<Image style={styles.img} source={{uri: row.images.medium}}/>
</View>
<View style={{flex:1}}>
<Text style={styles.mainTitle} numberOfLines={1}>
名称:{row.title}
</Text>
<Text style={styles.textWitdh} numberOfLines={1}>
演员:{names}
</Text>
<Text style={styles.textWitdh} numberOfLines={1}>
时间:{row.year} 评分:{row.rating.average}
</Text>
<Text style={styles.textWitdh} numberOfLines={1}>
标签:{row.genres}
</Text>
</View>
</View>
);
}
_getData(){
var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
var that = this;
var baseURL = ServiceURL.movie_search + '?count=10&q=' + this.state.keywords;
this.setState({
show: false
});
Util.get(baseURL, function(data){
if(!data.subjects || !data.subjects.length){
return alert('获取数据出错');
}
var subjects = data.subjects;
that.setState({
dataSource: ds.cloneWithRows(subjects),
show: true
});
}, function(err){
alert(err);
});
}
}
var styles = StyleSheet.create({
flex_1:{
flex:1,
marginTop:60,
},
row:{
flexDirection:'row'
},
img:{
width:80,
height:110,
resizeMode: Image.resizeMode.contain
},
textWitdh:{
flex:1,
marginLeft:15,
},
mainTitle:{
flex:1,
marginLeft:15,
fontSize:17,
},
item:{
backgroundColor:'#F1F2F3',
marginTop:0,
height:140,
paddingTop:15,
paddingBottom:5,
paddingLeft:10,
borderBottomWidth:Util.pixel,
borderTopWidth:Util.pixel,
borderColor:"#ddd"
},
});
网友评论