当前位置: 移动技术网 > IT编程>开发语言>JavaScript > React Native中ScrollView组件轮播图与ListView渲染列表组件用法实例分析

React Native中ScrollView组件轮播图与ListView渲染列表组件用法实例分析

2020年03月09日  | 移动技术网IT编程  | 我要评论

本文实例讲述了react native中scrollview组件轮播图与listview渲染列表组件用法。分享给大家供大家参考,具体如下:

1、scroll view

scrollview是react native提供的滚动视图组件,渲染一组视图,用户可以进行滑动响应交互,其常用属性如下:

滚动的偏移量:通过event.nativeevent.contentoffset.x可以得到水平偏移量。

  • horizontal={bool},属性为true时,所有子视图在水平方向排列,否则在纵向排列。默认为false。
  • pagingenabled={bool},属性为true时,滚动会停留在视图尺寸整数倍位置上,即正好显示某个视图,默认为false
  • scrollenabled={bool},值为false时,视图不能滚动,默认true
  • showshorizontalscrollindicator={bool},值为true在滚动时会在屏幕底部显示一个滚动条,默认true
  • showsverticalscrollindicator={bool},值为true在滚动时显示垂直方向的滚动条,默认true。
  • keyboarddismissmode="none"/"on-drag",滑动视图时是否隐藏软键盘,默认none不隐藏。
  • oncontentchange={function},当scrollview视图大小发生变化时调用函数。
  • onscroll={function},当滚动视图时调用函数。
  • onmomentumscrollstart={function},滚动开始调用函数。
  • onmomentumscrollend={function},滚动结束时调用函数。

组件所属的方法有:

  • scrollto({x:num,y:num,animated:bool}),组件视图滚动到指定x,y位置,第三个参数为是否启用动画
  • scrolltoend({animated:bool}),滚动到视图末尾。

例如利用scrollview来实现一个banner轮播:

页面结构如下:

<view style={styles.banner}>
 <scrollview ref="scrollview"   horizontal={true}
       pagingenabled={true} showshorizontalscrollindicator={false}
       onmomentumscrollend={(e)=>this.slide(e)}
       onscrollbegindrag={()=>{this.stoptimer()}}   //用户拖拽时停止自动轮播
       onscrollenddrag={()=>{this.settimer()}}    //拖拽结束后开始自动切换
 >
  {/*渲染轮播图片*/}
  {this.renderbanner()}
 </scrollview>
 <view style={styles.indicatebar}>
  {/*渲染底部指示标签点*/}
  {this.renderindicate()}
 </view>
</view>

利用map遍历数据数组zodiac,将图片渲染到页面

renderbanner(){
 return zodiac.map((item,index)=>
  <image key={index} source={{uri:'asset:/zodiac/'+item.image+'.jpg'}} style={styles.itemimage} />
 )
}

在底部渲染指示点:

renderindicate(){
 let jsx=[];
 for (let i=0;i<zodiac.length;i++){
  //判断是否为当前页,若为当前页则指示点color为蓝色,否则为白色
  if (i===this.state.pageindex){
   jsx.push(<text key={i} style={{fontsize:15,color:'#5cb0ff'}}>●</text>)
  }else {
   jsx.push(<text key={i} style={{fontsize:15,color:'#ffffff'}}>●</text>)
  }
 }
 return jsx;
}

当用户滑动结束时触发scrollview的onmomentumscrollend方法,调用slide函数,并传递event参数给slide。通过计算得出用户滑到的当前页的索引pageindex,其中页码的计算就是将x偏移量除以每个视图的宽度然后取整

slide(e){
 let offset=e.nativeevent.contentoffset.x;      //获取x偏移量
 let index=math.floor(offset/devwidth);       //通过偏移量计算出当前页码
 this.setstate({
  pageindex:index
 })
}

设置定时器让视图自动更换,通过setinterval让pageindex隔一段时间自动+1,然后让图片偏移到页码对应的图片,令页面索引乘以每个页面宽度即为当前页面对应的偏移量:

settimer(){
 this.timer=setinterval(()=>{
  this.setstate((prestate)=>{           //更新pageindex
   if(prestate.pageindex>=(zodiac.length-1)){   //如果页码达到上界则归零
    return {pageindex:0}
   }else {
    return {pageindex:prestate.pageindex+1}        //否则页码加一
   }
  });
  // 让图片偏移到页码所对应的页面
  let offset=this.state.pageindex*devwidth;  
  this.refs.scrollview.scrollto({x:offset,y:0,animated:true});
 },2000)
}

在组件销毁时清除定时器

componentwillunmount() {
 clearinterval(this.timer);
}

2、list view

<listview>用于将一组相同类型的数据渲染到页面上,你只需要定义好数据源与单个组件如何渲染,它便会将所有数据渲染完成。例如将如下左边json数据渲染为右边icon列表:

 

使用步骤如下

1、定义数据源,在constructor中初始化state,创建一个datasource对象,在state中定义数据源iconsource为外部导入的json数据icons,格式如下:

let icons=require('./mockdata/icons.json').data;
constructor(props){
 super(props);
 let datasource = new listview.datasource({rowhaschanged:(r1,r2)=>r1!==r2});
 this.state={
  iconsource:datasource.clonewithrows(icons),
 }
}

其中{rowhaschaged:(r1,r2)=>r1!==r2},是告诉listview当数据源变化时再重新渲染。

2、在页面使用<listview>,设置数据源datasource,内部样式contentcontainerstyle,每个元素的渲染方式renderrow为rendericon

<listview datasource={this.state.iconsource} contentcontainerstyle={styles.iconlist}
     renderrow={this.rendericon}
/>

3、实现渲染函数rendericon,默认传入四个参数:

  • rowdata:每个元素对应的数据
  • sectionid:元素所属分区
  • rowid:元素的id
  • highlightrow:通过调用此方法可以使某一行处于高亮

在rendericon函数中定义每一个icon图标的渲染的方式,并返回jsx:

rendericon(rowdata,sectionid,rowid,highlightrow){
 return(
  <touchableopacity activeopacity={0.5}>
   <view key={rowid} style={styles.iconitem}>
    <image style={styles.iconimg} source={{uri:'mipmap/'+rowdata.image}} />
    <text style={styles.icontitle}>{rowdata.title}</text>
   </view>
  </touchableopacity>
 )
}

3、使用listview渲染二维数据

以上例子中的data是个一维数组,数组每个元素中包含title与image两个字段,如果data是个二维数组,例如

 

其中data数组的一维元素中包含title与cars,而cars又是一个数组。使用listview将其渲染为上面右图所示按首字母分类的列表。

存储原理:

listview使用datablob来存储二维数据,其结构如下:

 

datablob按照一定的格式组织二维数据,如上左图。datablob首先存储数组的第一维section并为其分配id,例如将上面的一维数组的"title":"a",存储为datablob[0]="title":"a",分配sectionid为0,"title":"b",存储为datablob[1]="title":"b",分配id为1......以此类推。

之后再存储数组的第二维row,例如"cars":[{"name":"奥迪","icon": "m_9_100.png"}],它的第一维sectionid为0,第二维rowid为2,将其存储为datablob[0:2]={"name":"奥迪","icon": "m_9_100.png"}。

listview使用步骤如下:

1、设置数据源

与一维listview使用类似,首先在constructor中设置state为datasource对象:

this.state={
 cardata:new listview.datasource({
  getsectiondata:(datablob,sectionid)=>datablob[sectionid],  //设置sectiondata获取方式
  getrowdata:(datablob,sectionid,rowid)=>datablob[sectionid+':'+rowid],  //设置rowdata获取方式
  sectionheaderhaschanged:(s1,s2)=>s1!==s2,  //设置section更新方式
  rowhaschanged:(r1,r2)=>r1!==r2        //设置row更新方式
 })
}

在新建datasource对象时需要传递四个函数参数

  • getsectiondata:定义获取section的方式,它接收两个参数,datablob对象与sectionid,例如要获取上面提到的datablob[0]="title":"a" ,则通过datablob[sectionid]就可以返回"title":"a"。
  • getrowdata:获取row的方式,同理,通过datablob[0:2]可以得到{"name":"奥迪","icon": "m_9_100.png"}
  • sectionheaderhaschanged:定义section什么时候更新,接收两个参数s1,s2分别为前后两个状态,不同时才会重新渲染section
  • rowhaschanged:定义row什么时候更新

2、在页面中使用listview

使用list view时设置其数据源及渲染方法

<listview style={styles.carlist}
     datasource={this.state.cardata}        //定义数据源
     renderrow={this.rendercarrow}         //定义row的渲染方法
     rendersectionheader={this.rendercarsection}  //定义sectionheader渲染方法
/>

3、实现渲染方法,方法默认会传入参数rowdata与sectiondata

rendercarsection(sectiondata){
 return(
  <view style={styles.sectionbar}>
   <text style={styles.sectiontxt}>{sectiondata}</text>
  </view>
 )
}
rendercarrow(rowdata){
 return(
  <touchableopacity activeopacity={0.5}>
   <view style={styles.caritem}>
    <image source={{uri:'asset:/cars/'+rowdata.icon}} style={styles.carimg} />
    <text style={styles.cartitle}>{rowdata.name}</text>
   </view>
  </touchableopacity>
 )
}

4、将数据放入datablob

在组件挂载完成后将数据按照格式放入datablob并更新数据源,使数据加载到页面

componentdidmount() {
 this.loadcardata();
}
loadcardata(){
 let datablob={},      //datablob对象
  sectionids=[],      //sectionid数组
  rowids=[],        //rowid数组
  cars=[];
 for (let i=0;i<cardata.length;i++){    //循环遍历二维数据cardata  
  sectionids.push(i);           //将一维下标i当作sectionid
  datablob[i]=cardata[i].title;      //将section数据放入datablob第一维
  rowids[i]=[];              //初始化rowid数组的每个元素为一个数组
  cars=cardata[i].cars;          //拿到每个section下的cars数组
  for (let j=0;j<cars.length;j++){    //遍历section下的cars数组
   rowids[i].push(j);          //二维数组rowids[i][j]
   datablob[i+':'+j]=cars[j];      //将每行row数据放入datablob[i:j]第二维
  }
 }
 this.setstate({              //更新state中的数据源cardata,需要传入三个参数
  cardata:this.state.cardata.clonewithrowsandsections(datablob,sectionids,rowids)
 })
}

希望本文所述对大家react程序设计有所帮助。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网