React Native控件之ListView

概述

ListView作为核心组件之一,主要用于高效地显示一个可以垂直滚动的变化的数据列表。经过自定义组装,我们还可以用它实现九宫格等页面效果。 在React Native中,使用ListView组件至少需要两个属性:DataSource和renderRow。DataSource是需要渲染界面的数据源,renderRow是根据数据源的元素返回的可渲染的组件,即ListView的一行。 在React Native中,最基本的使用方式就是创建一个ListView.DataSource数据源,然后给它传递一个普通的数据数组,再使用数据源来实例化一个ListView组件,并且定义它的renderRow回调函数,这个函数返回ListView的一行作为一个可渲染的组件。例如,官网提供的ListView示例:

constructor(props) {
  super(props);
  var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
  this.state = {
    dataSource: ds.cloneWithRows(['第一行', '第二行', '第三行']),
  };
}
//省略…
render() {
  return (
    <ListView
      dataSource={this.state.dataSource}
      renderRow={(rowData) => <Text>{rowData}</Text>}
    />
  );}

属性

ListView组件主要有两个属性:dataSource和renderRow。其他常用的属性如下: dataSource 数据源 renderRow ListView渲染的每一item view initialListSize 初始渲染item的个数 pageSize 每次事件循环(每帧)渲染的行数 onEndReachedThreshold 调用onEndReached之前的临界值,单位是像素 onEndReached 当所有的数据都已经渲染过,并且列表被滚动到距离最底部不onEndReachedThreshold个像素的距离时调用

获取网络数据渲染界面

从现在开始,我们将实现一个从网络获取数据并使用ListView控件渲染界面的过程。效果如下:

1,创建构造器

我们在构造器中声明了一个成员变量state,并为它定义了两个属性,dataSource和loaded 。

constructor(props) {  
    super(props);  
    this.state = {  
        dataSource: new ListView.DataSource({  
            rowHasChanged: function(row1, row2) {return row1 !== row2},  
        }),  
        loaded: false,  
    };  
}

由于dataSource是弱类型,所以不用声名类型,重点看ListView实例化的部分。rowHasChanged是ListView必须要实现的一个function,否则会报错。一般我们会使用下面的简洁写法:

rowHasChanged: (row1, row2) => row1 !== row2  

2,处理componentDidMount回调

Component有一个回调函数componentDidMount(),它在所有UI组建加载完成后会被调用,类似于Android中Activity生命周期的onCreate,通常我们在它被回调的时候发起网络请求。

componentDidMount(){  
this.fetchData();  
}  

fetchData方法是我们自定义的请求网络的方法 。

 fetchData() {  
     fetch(REQUEST_URL)  
         .then((response) => response.json())  
         .then((responseData) => {  
 console.log(responseData);  
             this.setState({  
                 dataSource: this.state.dataSource.cloneWithRows(responseData.movies),  
                 loaded: true,  
             });  
         }).catch(function(e){         

})  
         .done();  
 }  

当网络返回数据之后,我们需要对dataSource进行通知更新操作。

3,渲染单个Cell视图

ListView界面由一个一个子视图组成,我们需要在render的时候渲染子视图,通常为了代码维护的方便,我们会将子视图通过自定义为视图使用。

renderCell(cellData) {
       return (
           <View style={styles.cellContainer}>
               <Image
                  //  source={{uri:cellData.pic}}
                  source={require('./image/defalt_image.png')}
                   style={styles.thumbnail}
               />
               <View style={styles.itemCellView}>
                   <Text numberOfLines={1} style={styles.title}>{cellData.title}</Text>
                   <Text numberOfLines={1} style={styles.id}>{cellData.actor}</Text>
               </View>
           </View>
       );
   }

}

4,ListView渲染整个界面

使用ListView渲染整个界面。

return (  
            <ListView  
                dataSource={this.state.dataSource}  
                renderRow={this.renderMovie}  
                style={styles.listView}  
            />  
        );

以下为全部代码:

import React, {  
    Component,  
} from 'react';  

import {  
     AppRegistry,  
     Image,  
     StyleSheet,  
     Text,  
     View,  
     ListView,  
 } from 'react-native';  



 var REQUEST_URL = 'https://raw.githubusercontent.com/facebook/react-native/master/docs/MoviesExample.json';  


 class DemoProject extends Component  
 {  
     constructor(props) {  
         super(props);  
         this.state = {  
             dataSource: new ListView.DataSource({  
                 rowHasChanged: (row1, row2) => row1 !== row2,  
             }),  
             loaded: false,  
         };  
     }  

     componentDidMount(){  
         this.fetchData();  
     }  

     fetchData() {  
         fetch(REQUEST_URL)  
             .then((response) => response.json())  
             .then((responseData) => {  
                 console.log(responseData);  
                 this.setState({  
                     dataSource: this.state.dataSource.cloneWithRows(responseData.movies),  
                     loaded: true,  
                 });  
             }).catch(function(e){  

             })  
             .done();  
     }  

     render() {  
         if (!this.state.loaded) {  
             return this.renderLoadingView();  
         }  

         return (  
             <ListView  
                 dataSource={this.state.dataSource}  
                 renderRow={this.renderMovie}  
                 style={styles.listView}  
             />  

         );  
     }  

     renderLoadingView()  
     {  
         return (<View style={styles.container} >  
                 <Text>Loading movies......</Text>  
             </View>  

         );  
     }  

     renderMovie(movie) {  
         return (  
             <View style={styles.container}>  
                 <Image  
                     source={{uri: movie.posters.thumbnail}}  
                     style={styles.thumbnail}  
                 />  
                 <View style={styles.rightContainer}>  
                     <Text style={styles.title}>{movie.title}</Text>  
                     <Text style={styles.year}>{movie.year}</Text>  
                 </View>  
             </View>  
         );  
     }  


 };  


 var styles = StyleSheet.create({  
     container: {  
         flex: 1,  
         flexDirection: 'row',  
         justifyContent: 'center',  
         alignItems: 'center',  
         backgroundColor: '#F5FCFF',  
     },  
     rightContainer: {  
         flex: 1,  
     },  
     title: {  
         fontSize: 20,  
         marginBottom: 8,  
         textAlign: 'center',  
     },  
     year: {  
         textAlign: 'center',  
     },  
     thumbnail: {  
         width: 53,  
         height: 81,  
     },  
     listView: {  
         paddingTop: 20,  
         backgroundColor: '#F5FCFF',  
     },  
 });  
 AppRegistry.registerComponent('AwesomeProject', () => DemoProject);  

注:如果你读取的是本地的数据,可以通过require获取,例如:

let data=require('./data/list.json');
      this.setState({
          dataSource:this.state.dataSource.cloneWithRows(data.list),
      });

附:ListView示例代码

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏lzj_learn_note

自定义无限循环ViewPager(二)――ViewPager滑动原理解析

在前面一篇文章中,已经分析了ViewPager初始化的原理,而本篇文章开始分析ViewPager的滑动及页面切换的原理。在阅读本文之前,大家可以先去了解下Scr...

22310
来自专栏進无尽的文章

UI篇-VC的生命周期以及UIView的layoutSubviews和drawRect方法

看似常用的UIView,其实有很多不经常用到的方法和应该注意的机制,我是一个喜欢打破砂锅问到底的人,可是很多问题在网上搜索不到答案,大部分的博客都是转载相同的东...

18630
来自专栏Android相关

LinearLayout.onMeasure--事例说明

将LinearLayout中代码Copy了一份存在本地,然后再在里面加了几个子View,打印出来LinearLayout.onMeasure中的那些变量的值

11420
来自专栏吴老师移动开发

【iOS开发】Responder Chain做事件传递

像商品详情这种有各种各样的cell,cell里面又有各种不同的按钮事件等。cell里面可能还有几层UI,如何将这种层级很多很复杂的UI页面的事件传递到Contr...

13530
来自专栏天天

基于cube-ui搭建移动端项目

cube-ui 搭配 webpack 2+ 支持后编译和普通编译 2 种构建方式(默认使用后编译),使用前都需要修改应用的依赖和配置。

46720
来自专栏向治洪

Android WindowManager详解

概述 WindowManager是Android中一个重要的服务(Service )。WindowManager Service 是全局的,是唯一的。它将用户的...

31490
来自专栏君赏技术博客

Jekyll-Admin-Mac 开发纪要-左侧菜单栏

本文章文字大约 4500字,大概花费 10分钟阅读。本文章设计的图片比较多,流量党慎入!。

18310
来自专栏Android源码框架分析

理解Android硬件加速原理的小白文

硬件加速,直观上说就是依赖GPU实现图形绘制加速,软硬件加速的区别主要是图形的绘制究竟是GPU来处理还是CPU,如果是GPU,就认为是硬件加速绘制,反之,软件绘...

32440
来自专栏Android开发小工

完全自定义样式的一句话实现RecyclerView的单选多选

今天的主题是封装RecyclerView的单选多选,现在大家应该都是用的RecyclerView开发列表数据吧。

22050
来自专栏一“技”之长

iOS8统一的系统提示控件——UIAlertController

        相信在iOS开发中,大家对UIAlertView和UIActionSheet一定不陌生,这两个控件在UI设计中发挥了很大的作用。然而如果你用过,...

8910

扫码关注云+社区

领取腾讯云代金券