本文实例讲述了React Native中ScrollView组件轮播图与ListView渲染列表组件用法。分享给大家供大家参考,具体如下:1、Scroll ViewScrollView是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},滚动结束时调用函数。
horizontal={bool},属性为true时,所有子视图在水平方向排列,否则在纵向排列。默认为false。pagingEnabled={bool},属性为true时,滚动会停留在视图尺寸整数倍位置上,即正好显示某个视图,默认为falsescrollEnabled={bool},值为false时,视图不能滚动,默认trueshowsHorizontalScrollIndicator={bool},值为true在滚动时会在屏幕底部显示一个滚动条,默认trueshowsVerticalScrollIndicator={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}),滚动到视图末尾。
scrollTo({x:num,y:num,animated:bool}),组件视图滚动到指定x,y位置,第三个参数为是否启用动画scrollToEnd({animated:bool}),滚动到视图末尾。例如利用ScrollView来实现一个Banner轮播:页面结构如下:

horizontal={true}

pagingEnabled={true} showsHorizontalScrollIndicator={false}

onMomentumScrollEnd={(e)=>this.slide(e)}

onScrollBeginDrag={()=>{this.stopTimer()}}
//用户拖拽时停止自动轮播

onScrollEndDrag={()=>{this.setTimer()}}
//拖拽结束后开始自动切换
>

{/*渲染轮播图片*/}

{this.renderBanner()}



{/*渲染底部指示标签点*/}

{this.renderIndicate()}





horizontal={true}

pagingEnabled={true} showsHorizontalScrollIndicator={false}

onMomentumScrollEnd={(e)=>this.slide(e)}

onScrollBeginDrag={()=>{this.stopTimer()}}
//用户拖拽时停止自动轮播

onScrollEndDrag={()=>{this.setTimer()}}
//拖拽结束后开始自动切换
>

{/*渲染轮播图片*/}

{this.renderBanner()}



{/*渲染底部指示标签点*/}

{this.renderIndicate()}



利用map遍历数据数组zodiac,将图片渲染到页面
renderBanner(){
return zodiac.map((item,index)=>


)
}


renderBanner(){
return zodiac.map((item,index)=>


)
}

在底部渲染指示点:
renderIndicate(){
let jsx=[];
for (let i=0;i
//判断是否为当前页,若为当前页则指示点color为蓝色,否则为白色

if (i===this.state.pageIndex){

jsx.push()

}else {

jsx.push()

}
}
return jsx;
}


renderIndicate(){
let jsx=[];
for (let i=0;i
//判断是否为当前页,若为当前页则指示点color为蓝色,否则为白色

if (i===this.state.pageIndex){

jsx.push()

}else {

jsx.push()

}
}
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
})
}


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)
}


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);
}
componentWillUnmount() {
clearInterval(this.timer);
}2、List View用于将一组相同类型的数据渲染到页面上,你只需要定义好数据源与单个组件如何渲染,它便会将所有数据渲染完成。例如将如下左边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),
}
}


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当数据源变化时再重新渲染。{rowHasChaged:(r1,r2)=>r1!==r2}2、在页面使用,设置数据源dataSource,内部样式contentContainerStyle,每个元素的渲染方式renderRow为renderIcon

renderRow={this.renderIcon}
/>



renderRow={this.renderIcon}
/>

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

rowData:每个元素对应的数据

sectionId:元素所属分区

rowId:元素的id

highlightRow:通过调用此方法可以使某一行处于高亮
rowData:每个元素对应的数据sectionId:元素所属分区rowId:元素的idhighlightRow:通过调用此方法可以使某一行处于高亮在renderIcon函数中定义每一个icon图标的渲染的方式,并返回JSX:
renderIcon(rowData,sectionId,rowId,highlightRow){
return(







{rowData.title}




)
}


renderIcon(rowData,sectionId,rowId,highlightRow){
return(







{rowData.title}




)
}

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使用步骤如下: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更新方式
})
}


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什么时候更新
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分别为前后两个状态,不同时才会重新渲染sectionrowHasChanged:定义row什么时候更新2、在页面中使用ListView使用List View时设置其数据源及渲染方法

dataSource={this.state.carData}
//定义数据源

renderRow={this.renderCarRow}
//定义row的渲染方法

renderSectionHeader={this.renderCarSection}
//定义SectionHeader渲染方法
/>



dataSource={this.state.carData}
//定义数据源

renderRow={this.renderCarRow}
//定义row的渲染方法

renderSectionHeader={this.renderCarSection}
//定义SectionHeader渲染方法
/>

3、实现渲染方法,方法默认会传入参数rowData与sectionData
renderCarSection(sectionData){
return(



{sectionData}


)
}
renderCarRow(rowData){
return(







{rowData.name}




)
}


renderCarSection(sectionData){
return(



{sectionData}


)
}
renderCarRow(rowData){
return(







{rowData.name}




)
}

4、将数据放入dataBlob在组件挂载完成后将数据按照格式放入dataBlob并更新数据源,使数据加载到页面
componentDidMount() {
this.loadCarData();
}
loadCarData(){
let dataBlob={},
//dataBlob对象

sectionIDs=[],
//sectionID数组

rowIDs=[],
//rowID数组

cars=[];
for (let i=0;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//遍历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)
})
}


componentDidMount() {
this.loadCarData();
}
loadCarData(){
let dataBlob={},
//dataBlob对象

sectionIDs=[],
//sectionID数组

rowIDs=[],
//rowID数组

cars=[];
for (let i=0;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//遍历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程序设计有所帮助。