React-Native 之 ScrollView介紹和使用


前言

  • 學習本系列內容需要具備一定 HTML 開發基礎,沒有基礎的朋友可以先轉至 HTML快速入門(一) 學習

  • 本人接觸 React Native 時間並不是特別長,所以對其中的內容和性質了解可能會有所偏差,在學習中如果有錯會及時修改內容,也歡迎萬能的朋友們批評指出,謝謝

  • 文章第一版出自簡書,如果出現圖片或頁面顯示問題,煩請轉至 簡書 查看 也希望喜歡的朋友可以點贊,謝謝

ScrollView組件介紹與簡單使用


  • React Native中的 ScrollView 的組件除了包裝滾動平台,還集成了觸摸鎖定的 響應者 系統,使用的時候有幾點需要注意

    • ScrollView 必須有一個確定的高度才能正常工作,對於 ScrollView 來說,它就是將一些不確定高度的子組件裝進確定高度的容器
    • 初始化的2中方式
      • 不要給 ScrollView 中不要加 [flex:1]
      • 直接給該 ScrollView 設置高度(不建議),因為它會根據內部組件自動延伸自己的尺寸到合適的大小
    • ScrollView 內部的其它響應者沒辦法阻止 ScrollView 本身成為響應者(也就是說,ScrollView 響應的優先級比內部組件高,且內部組件沒辦法改變優先級)
  • 那么就先來看看怎么創建基本的 ScrollView

    • 視圖部分


    	// 視圖
    	var CustomScrollView = React.createClass({
    		render(){
        		return(
            		<ScrollView style={styles.mainStyle}>
                		{this.renderItem()}
            		</ScrollView>
        		);
    		},
    
    		renderItem() {
        		// 數組
        		var itemAry = [];
        		// 顏色數組
        		var colorAry = ['gray', 'green', 'blue', 'yellow', 'black', 'orange'];
        		// 遍歷
        		for (var i = 0; i<colorAry.length; i++) {
            		itemAry.push(
                		<View key={i} style={[styles.itemStyle, {backgroundColor: colorAry[i]}]}></View>
            		);
        		}
        		return itemAry;
    		}
    	});
    
    
    • 樣式部分


    	// 樣式
    	var styles = StyleSheet.create({
    		scrollViewStyle: {
        		// 背景色
        		backgroundColor:'red'
    		},
    
    		itemStyle: {
        		// 尺寸
        		width:1000,
        		height:200
    		},
    	});
    
    

    效果:
    ScrollView基本使用.gif

ScrollView 中常用的屬性


  • 下面經常使用和比較難理解的屬性會有示例代碼或效果圖

  • contentContainerStyle:這些樣式會引用到一個內層的內容容器上,所有的子視圖都會包裹在內容容器內

  • horizontal:當此屬性為true的時候,所有的的子視圖會在水平方向上排成一行,而不是默認的在垂直方向上排成一列。默認值為false

    	<ScrollView style={styles.scrollViewStyle}
                    horizontal={true}
            >
            {this.renderItem()}
        </ScrollView>
    
    

    效果:
    horizontal屬性.gif

  • keyboardDismissMode:用戶拖拽滾動視圖的時候,是否要隱藏軟鍵盤。

    • none(默認值),拖拽時不隱藏軟鍵盤
    • on-drag 當拖拽開始的時候隱藏軟鍵盤
    • interactive 軟鍵盤伴隨拖拽操作同步地消失,並且如果往上滑動會恢復鍵盤。安卓設備上不支持這個選項,會表現的和none一樣。
  • keyboardShouldPersistTaps:當此屬性為false的時候,在軟鍵盤激活之后,點擊焦點文本輸入框以外的地方,鍵盤就會隱藏。如果為true,滾動視圖不會響應點擊操作,並且鍵盤不會自動消失。默認值為false

  • refreshControl:指定RefreshControl組件,用於為ScrollView提供下拉刷新功能

  • removeClippedSubviews:(實驗特性)當此屬性為true時,屏幕之外的子視圖(子視圖的overflow樣式需要設為hidden)會被移除。這個可以提升大列表的滾動性能。默認值為true

    	var styles = StyleSheet.create({  
    		child: {
    			...
    			// 因為默認為true,所以我們只需要在子視圖將下面樣式設為hidden就可以了
    			overflow: 'hidden'
    		},
    	});
    
    
  • showsHorizontalScrollIndicator:當此屬性為true的時候,顯示一個水平方向的滾動條

    	<ScrollView style={styles.scrollViewStyle}
    				 horizontal={true}
            		 showsHorizontalScrollIndicator={true}
            >
            {this.renderItem()}
        </ScrollView>
    
    

    效果:
    顯示水平滾動條.png

  • showsVerticalScrollIndicator:當此屬性為true的時候,顯示一個垂直方向的滾動條

    	<ScrollView style={styles.scrollViewStyle}
                    showsVerticalScrollIndicator={true}
            >
            {this.renderItem()}
        </ScrollView>
    
    

    效果:
    顯示垂直滾動條.png

  • endFillColor:有時候滾動視圖會占據比實際內容更多的空間。這種情況下可以使用此屬性,指定以某種顏色來填充多余的空間,以避免設置背景和創建不必要的繪制開銷。一般情況下並不需要這種高級優化技巧

  • alwaysBounceHorizontal:當此屬性為true時,水平方向即使內容比滾動視圖本身還要小,也可以彈性地拉動一截。當horizontal={true}時(默認值為true)否則為false

    	<ScrollView style={styles.scrollViewStyle}
    				 horizontal={true}
                    alwaysBounceHorizontal={true}
            >
            {this.renderItem()}
        </ScrollView>
    
    

    效果:
    alwaysBounceHorizontal屬性.gif

  • alwaysBounceVertical:當此屬性為true時,垂直方向即使內容比滾動視圖本身還要小,也可以彈性地拉動一截。當horizontal={true}時(默認值為false),否則為true

    	<ScrollView style={styles.scrollViewStyle}
                    horizontal={true}
                    alwaysBounceVertical={true}
            >
            {this.renderItem()}
        </ScrollView>
    
    

    效果:
    alwaysBounceVertical屬性.gif

  • automaticallyAdjustContentInsets:如果滾動視圖放在一個導航條或者工具條后面的時候,iOS系統是否要自動調整內容的范圍。默認值為true。(譯注:如果你的ScrollView或ListView的頭部出現莫名其妙的空白,嘗試將此屬性置為false)

  • bounces:當值為true時,如果內容范圍比滾動視圖本身大,在到達內容末尾的時候,可以彈性地拉動一截。如果為false,尾部的所有彈性都會被禁用,即使alwaysBounce*屬性為true。默認值為true

    	<ScrollView style={styles.scrollViewStyle}
                    bounces={false}
            >
            {this.renderItem()}
        </ScrollView>
    
    

    效果:
    bounces屬性為false時.gif

  • bouncesZoom:當值為true時,使用手勢縮放內容可以超過min/max的限制,然后在手指抬起之后彈回min/max的縮放比例。否則的話,縮放不能超過限制

  • canCancelContentTouches:當值為false時,一旦有子節點響應觸摸操作,即使手指開始移動也不會拖動滾動視圖。默認值為true(在以上情況下可以拖動滾動視圖)

  • centerContent:當值為true時,如果滾動視圖的內容比視圖本身小,則會自動把內容居中放置。當內容比滾動視圖大的時候,此屬性沒有作用。默認值為false

  • contentInset:{top: number, left: number, bottom: number, right: number}內容范圍相對滾動視圖邊緣的坐標。默認為{0, 0, 0, 0}

  • contentOffset:用來手動設置初始的滾動坐標。默認值為{x: 0, y: 0}

  • decelerationRate:一個浮點數,用於決定當用戶抬起手指之后,滾動視圖減速停下的速度。常見的選項有:

    • Normal: 0.998 (默認值)
    • Fast: 0.9
  • directionalLockEnabled:當值為真時,滾動視圖在拖拽的時候會鎖定只有垂直或水平方向可以滾動。默認值為false

  • maximumZoomScale:允許的最大縮放比例。默認值為1.0

  • minimumZoomScale:允許的最小縮放比例。默認值為1.0

  • pagingEnabled:當值為true時,滾動條會停在滾動視圖的尺寸的整數倍位置。這個可以用在水平分頁上。默認值為false

    	<ScrollView style={styles.scrollViewStyle}
                    horizontal={true}
                    pagingEnabled={true}
            >
            {this.renderItem()}
        </ScrollView>
    
    

    效果:
    pagingEnabled分頁屬性.gif

  • scrollEnabled:當值為false的時候,內容不能滾動,默認值為true

    	<ScrollView style={styles.scrollViewStyle}
                    scrollEnabled={false}
            >
            {this.renderItem()}
        </ScrollView>
    
    

    效果:
    scrollEnabled屬性為false時不能滾動.gif

  • scrollEventThrottle:這個屬性控制在滾動過程中,scroll事件被調用的頻率(單位是每秒事件數量)。更大的數值能夠更及時的跟蹤滾動位置,不過可能會帶來性能問題,因為更多的信息會通過bridge傳遞。默認值為0,意味着每次視圖被滾動,scroll事件只會被調用一次

  • scrollIndicatorInsets:{top: number, left: number, bottom: number, right: number}決定滾動條距離視圖邊緣的坐標。這個值應該和contentInset一樣。默認值為{0, 0, 0, 0}

  • scrollsToTop:當此值為true時,點擊狀態欄的時候視圖會滾動到頂部。默認值為true

    	<ScrollView style={styles.scrollViewStyle}
                    scrollsToTop={true}
            >
            {this.renderItem()}
        </ScrollView>
    
    

    效果:
    scrollsToTop為true時點擊狀態欄可快速回到頂部.gif

  • snapToAlignment:enum('start', "center", 'end')當設置了snapToInterval,snapToAlignment會定義停駐點與滾動視圖之間的關系。

    • start (默認) 會將停駐點對齊在左側(水平)或頂部(垂直)
    • center 會將停駐點對齊到中間
    • end 會將停駐點對齊到右側(水平)或底部(垂直)
  • snapToInterval:當設置了此屬性時,會讓滾動視圖滾動停止后,停止在 snapToInterval 的倍數的位置。這可以在一些子視圖比滾動視圖本身小的時候用於實現分頁顯示 snapToAlignment 組合使用

  • stickyHeaderIndices:一個子視圖下標的數組,用於決定哪些成員會在滾動之后固定在屏幕頂端。舉個例子,傳遞 stickyHeaderIndices={[0]} 會讓第一個成員固定在滾動視圖頂端。這個屬性不能和 horizontal={true} 一起使用

    	<ScrollView style={styles.scrollViewStyle}
                    stickyHeaderIndices={[0]}
            >
            {this.renderItem()}
        </ScrollView>
    
    

    效果:
    stickyHeaderIndices屬性.gif

  • zoomScale:滾動視圖內容初始的縮放比例。默認值為1.0

  • onMomentumScrollEnd:當一幀滾動完畢的時候調用,通過 e.nativeEvent.contentOffset 獲取偏移量

  • onScrollBeginDrag:當開始手動拖拽的時候調用

  • onScrollEndDrag:當結束手動拖拽的時候調用

  • onScrollAnimationEnd:當滾動動畫結束之后調用此回調

  • onContentSizeChange:此函數會在ScrollView內部可滾動內容的視圖發生變化時調用

    • 調用參數為內容視圖的寬和高: (contentWidth, contentHeight)
    • 此方法是通過綁定在內容容器上的onLayout來實現的
  • onScroll:在滾動的過程中,每幀最多調用一次此回調函數。調用的頻率可以用scrollEventThrottle屬性來控制(在Android不好使,而且影響性能

  • )

方法


  • scrollTo:(y: number | { x?: number, y?: number, animated?: boolean }, x: number, animated: boolean)滾動到指定的x, y偏移處。第三個參數為是否啟用平滑滾動動畫

ScrollView綜合使用實例


  • 這邊通過所有 ScrollView 入門編程的經典案例 —— 圖片輪播器更全面地理解 ScrollView 的使用

  • 為了更貼切實際開發,這邊使用JSON來包裝圖片數據,內容如下圖

    JSON數據詳情.png

  • 先來實例化一個ScrollView與其內部的子視圖,並進行一些測試必要的設置

    • 先獲取json中的數據


    	// 獲取json中的數據
    	var imageData = require('./Data/ImageData.json');
    
    
    • 接着我們來完成視圖部分


    	// 視圖
    	var CustomScrollView = React.createClass({
    		render(){
        		return(
            		<View style={styles.container}>
                		{/* 實例化ScrollView */}
                		<ScrollView style={styles.scrollViewStyle}
                            		horizontal={true}   // 水平方向
                            		showsHorizontalScrollIndicator={false}  // 隱藏水平指示器
                            		showsVerticalScrollIndicator={false}    // 隱藏垂直指示器
                            		pagingEnabled={true}    // 開啟分頁功能
                >
                    		{/* 實例化內部子視圖 */}
                    		{this.renderItem()}
                		</ScrollView>
    
                	
            		</View>
        		);
    		},
    
    		// scrollView子視圖
    		renderItem() {
        		var itemAry = [];
    
        		// 獲取json中圖片
        		var imgAry = imageData.data;
    
        		// 根據json數據實例化視圖
        		for (var i = 0; i<imgAry.length; i++) {
            		// 取出單個對象
            		var item = imgAry[i];
            		// 將子視圖放進 itemAry
            		itemAry.push(
                		// 實例化子視圖
                		<Image key={i} style={styles.itemStyle} source={{uri:item.img}} />
            		)
        		}
    
        		// 返回數組
        		return itemAry;
    		},
    	});
    
    
    • 最后是樣式部分


    	// 樣式
    	var styles = StyleSheet.create({
    		container: {
        		backgroundColor:'white'
    		},
    
    		scrollViewStyle: {
        		// 背景色
        		backgroundColor:'yellow',
        		// 上邊距
        		marginTop:20
    		},
    
    		itemStyle: {
        		// 尺寸
        		width:width,
        		height:200,
        		// 圖片等比例拉伸
        		resizeMode:'contain'
    		},
    	});
    

    效果:

圖片輪播器效果.gif

  • 圖片輪播器肯定要有分頁指示器,接下來我們就來制作

    • 視圖部分


    	// 先初始化頁碼,確定初始化后顯示哪個頁面
    	getInitialState(){
        	return{
            	// 初始化當前頁碼
            	currentPage:0
        	}
    	},
    	
    
    • 實例化一個分頁指示器


    	{/* 實例化分頁指示器 */}
        <View style={styles.pagingIndicatorStyle}>
               {this.renderPagingIndicator()}
        </View>
    
    	
    	// 分頁指示器
    	renderPagingIndicator() {
        	var itemAry = [], autoColor;
    
        	// 獲取json中圖片
        	var  imgAry = imageData.data;
    
        	// 根據json數據實例化視圖
        	for (var i = 0; i<imgAry.length; i++) {
            	// 取出單個對象
            	var item = imgAry[i];
    
            	// 跟隨當前頁改變對應 點 的顏色
            	autoColor = (this.state.currentPage === i) ? {color:'orange'} : {color:'white'}
    
            	// 將子視圖放進 itemAry
            	itemAry.push(
                	// 實例化視圖
                	<Text key={i} style={[{fontSize:30}, autoColor]}>&bull;</Text>
            	)
        	}
    
        	// 返回數組
        	return itemAry;
    	},
    
    
    • 樣式部分


    	pagingIndicatorStyle: {
        	// 背景色(使背景色為全透明)
        	backgroundColor:'rgba(255,255,255,0.0)',
        	// 尺寸
        	width:width,
        	// 主軸方向與對齊方式
        	flexDirection:'row',
        	justifyContent:'center',
        	// 絕對定位,使頁碼指示器蓋在scrollView上面
        	position:'absolute',
        	bottom:0
    	}
    
    

    效果:

圖片輪播器效果.gif

  • 最后將完整代碼放出,供參考

    	import React, { Component } from 'react';
    	import {
    		AppRegistry,
    		StyleSheet,
    		Text,
    		View,
    		ScrollView,
    		Image
    	} from 'react-native';
    
    	// 引入Dimensions庫
    	var Dimensions = require('Dimensions');
    	var {width, height} = Dimensions.get('window');
    
    	// 獲取json中的數據
    	var imageData = require('./Data/ImageData.json');
    
    	// 視圖
    	var CustomScrollView = React.createClass({
    		// 先初始化頁碼,確定初始化后顯示哪個頁面
    		getInitialState(){
        		return{
            		// 初始化當前頁碼
            		currentPage:0
        		}
    		},
    
    		render(){
        		return(
            		<View style={styles.container}>
                		{/* 實例化ScrollView */}
                		<ScrollView style={styles.scrollViewStyle}
                            		horizontal={true}   // 水平方向
                            		showsHorizontalScrollIndicator={false}  // 隱藏水平指示器
                            		showsVerticalScrollIndicator={false}    // 隱藏垂直指示器
                            		pagingEnabled={true}    // 開啟分頁功能
                            		onMomentumScrollEnd={this.onAnimationEnd}   // 當一幀滾動完畢的時候調用
                		>
                    		{/* 實例化內部子視圖 */}
                    		{this.renderItem()}
                		</ScrollView>
    
               			{/* 實例化分頁指示器 */}
                		<View style={styles.pagingIndicatorStyle}>
                    		{this.renderPagingIndicator()}
               			</View>
            		</View>
        		);
    		},
    
    		// 監聽滾動
    		onAnimationEnd(e){
        		// 求出水平方向上的偏移量
        		var offSetX = e.nativeEvent.contentOffset.x;
        		// 計算當前頁碼
        		var currentPage = offSetX / width;
        		// 重新繪制UI
        		this.setState({
           			currentPage:currentPage
        		});
    		},
    
    		// 分頁指示器
    		renderPagingIndicator() {
        		var itemAry = [], autoColor;
    
        		// 獲取json中圖片
        		var  imgAry = imageData.data;
    
        		// 根據json數據實例化視圖
        		for (var i = 0; i<imgAry.length; i++) {
            		// 取出單個對象
            		var item = imgAry[i];
    
            		// 跟隨當前頁改變對應 點 的顏色
            		autoColor = (this.state.currentPage === i) ? {color:'orange'} : {color:'white'}
    
            		// 將子視圖放進 itemAry
            		itemAry.push(
                		// 實例化視圖
                		<Text key={i} style={[{fontSize:30}, autoColor]}>&bull;</Text>
            		)	
        		}
    
        		// 返回數組
        		return itemAry;
    		},
    
    		// scrollView子視圖
    		renderItem() {
       		 	var itemAry = [];
    
        		// 獲取json中圖片
        		var imgAry = imageData.data;
    
        		// 根據json數據實例化視圖
        		for (var i = 0; i<imgAry.length; i++) {
            		// 取出單個對象
            		var item = imgAry[i];
            		// 將子視圖放進 itemAry
            		itemAry.push(
                		// 實例化子視圖
                		<Image key={i} style={styles.itemStyle} source={{uri:item.img}} />
            		)
    			}
    
        		// 返回數組
        		return itemAry;
    		},
    	});
    
    	// 樣式
    	var styles = StyleSheet.create({
    		container: {
        		backgroundColor:'white'
    		},
    
    		scrollViewStyle: {
        		// 背景色
        		backgroundColor:'yellow',
        		// 上邊距
        		marginTop:20
    		},
    
    		itemStyle: {
        		// 尺寸
        		width:width,
        		height:200,
        		// 圖片等比例拉伸
        		resizeMode:'contain'
    		},
    
    	 	pagingIndicatorStyle: {
        		// 背景色(使背景色為全透明)
        		backgroundColor:'rgba(255,255,255,0.0)',
        		// 尺寸
        		width:width,
        		// 主軸方向與對齊方式
        		flexDirection:'row',
        		justifyContent:'center',
        		// 絕對定位,使頁碼指示器蓋在scrollView上面
        		position:'absolute',
        		bottom:0
    		}
    	});
    
    	module.exports = CustomScrollView;
    
    
  • 就先寫到這邊,如果有什么錯誤還請朋友們指出,有什么不清楚的也歡迎留言,喜歡的話記得點贊哦,謝謝!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM