本文實例講述了React Native中ScrollView組件輪播圖與ListView渲染列表組件用法。分享給大家供大家參考,具體如下:
ScrollView是React Native提供的滾動視圖組件,渲染一組視圖,用戶可以進行滑動響應交互,其常用屬性如下:
滾動的偏移量:通過event.nativeEvent.contentOffset.x可以得到水平偏移量。
組件所屬的方法有:
例如利用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);
}
<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,默認傳入四個參數:
在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>
)
}
以上例子中的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對象時需要傳遞四個函數參數
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程序設計有所幫助。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。