本文实例讲述了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程序设计有所帮助。
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
稳了!魔兽国服回归的3条重磅消息!官宣时间再确认!
昨天有一位朋友在大神群里分享,自己亚服账号被封号之后居然弹出了国服的封号信息对话框。
这里面让他访问的是一个国服的战网网址,com.cn和后面的zh都非常明白地表明这就是国服战网。
而他在复制这个网址并且进行登录之后,确实是网易的网址,也就是我们熟悉的停服之后国服发布的暴雪游戏产品运营到期开放退款的说明。这是一件比较奇怪的事情,因为以前都没有出现这样的情况,现在突然提示跳转到国服战网的网址,是不是说明了简体中文客户端已经开始进行更新了呢?
更新日志
- 凤飞飞《我们的主题曲》飞跃制作[正版原抓WAV+CUE]
- 刘嘉亮《亮情歌2》[WAV+CUE][1G]
- 红馆40·谭咏麟《歌者恋歌浓情30年演唱会》3CD[低速原抓WAV+CUE][1.8G]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[320K/MP3][193.25MB]
- 【轻音乐】曼托凡尼乐团《精选辑》2CD.1998[FLAC+CUE整轨]
- 邝美云《心中有爱》1989年香港DMIJP版1MTO东芝首版[WAV+CUE]
- 群星《情叹-发烧女声DSD》天籁女声发烧碟[WAV+CUE]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[FLAC/分轨][748.03MB]
- 理想混蛋《Origin Sessions》[320K/MP3][37.47MB]
- 公馆青少年《我其实一点都不酷》[320K/MP3][78.78MB]
- 群星《情叹-发烧男声DSD》最值得珍藏的完美男声[WAV+CUE]
- 群星《国韵飘香·贵妃醉酒HQCD黑胶王》2CD[WAV]
- 卫兰《DAUGHTER》【低速原抓WAV+CUE】
- 公馆青少年《我其实一点都不酷》[FLAC/分轨][398.22MB]
- ZWEI《迟暮的花 (Explicit)》[320K/MP3][57.16MB]