1. 程式人生 > >react-native---rn中的滑動檢視元件(ScrollView)

react-native---rn中的滑動檢視元件(ScrollView)

ScrollView元件介紹與簡單使用

  • React Native中的 ScrollView 的元件除了包裝滾動平臺,還集成了觸控鎖定的 響應者 系統,使用的時候有幾點需要注意
//ScrollView 必須有一個確定的高度才能正常工作,對於 ScrollView 來說,它就是將一些不確定高度的子元件裝進確定高度的容器

//初始化的2中方式
1. 給 ScrollView 中加 [flex:1]

2. 直接給該 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 中常用的屬性

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

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

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

效果:
這裡寫圖片描述

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>

效果:
這裡寫圖片描述

showsVerticalScrollIndicator
當此屬性為true的時候,顯示一個垂直方向的滾動條(前提設定為垂直滾動)

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

效果:
這裡寫圖片描述

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

alwaysBounceHorizontal
當此屬性為true時,水平方向即使內容比滾動檢視本身還要小,也可以彈性地拉動一截。(前提是horizontal設定為true)

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

效果:
這裡寫圖片描述

alwaysBounceVertical
當此屬性為true時,垂直方向即使內容比滾動檢視本身還要小,也可以彈性地拉動一截。(前提horizontal設為true)

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

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

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

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

效果:
這裡寫圖片描述

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>

效果:
這裡寫圖片描述

scrollEnabled
當值為false的時候,內容不能滾動,預設值為true

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

效果:
這裡寫圖片描述

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>

效果:
這裡寫圖片描述

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>

效果:
這裡寫圖片描述

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來包裝圖片資料,內容如下圖

這裡寫圖片描述

先來例項化一個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'
        },
    });

效果:
這裡寫圖片描述

圖片輪播器肯定要有分頁指示器,接下來我們就來製作
檢視部分

// 先初始化頁碼,確定初始化後顯示哪個頁面
    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]}>•</Text>
            )
        }

        // 返回陣列
        return itemAry;
    },

樣式部分

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

效果:
這裡寫圖片描述

最後將完整程式碼放出,供參考

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]}>•</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;

轉載