ReactNative ViewPageAndroid元件詳解

Code4Android發表於2019-02-14

原始碼傳送門

在我們開發Android的時候,ViewPage這個控制元件的使用頻率還是很高的,最簡單的就是製作引導頁,應用程式的主介面等,在ReactNative開發中實現該功能的元件是ViewPageAndroid,當你看到該元件是以Android結尾,你就明白該元件只對Android平臺有效,如果使用就要考慮適配iOS(目前學習到的ScrollView元件可以實現此效果,具體實現不在本篇文章介紹),今天就通過下面示例圖,介紹ViewPageAndroid的API以及使用。

viewpage.gif
viewpage.gif

基本用法

對於該元件內部可以巢狀View,每一個子View就相當於一個Page,每一個單獨的頁面顯示時它會拉伸填滿ViewPageAndroid。

        return (
            <ViewPagerAndroid style={{backgroundColor: `red`, flex: 1}}>
                <View ><Text>1</Text></View>
                <View><Text>2</Text></View>
                <View><Text>3 </Text></View>
            </ViewPagerAndroid>
        )複製程式碼

在上面我麼給出了一個最簡單的展示ViewPagerAndroid的例子。我們在其內部加入了3個View,那麼也將顯示3頁,雖然View沒有設定樣式,如寬和高,,但是它會填充ViewPagerAndroid ,其實設定了寬和高也沒有用,不管設定寬高多少都是填滿ViewPageAndroid。如果不信你可以嘗試給第一個View新增樣式

style={{backgroundColor:`green`}}複製程式碼

設定後,發現第一頁顯示的背景是綠色。然後再給第一個View增加寬高屬性,都設定為100.如下

style={{backgroundColor:`green`,width:100,height:100}}複製程式碼

設定後發現第一頁的背景仍然全部是綠色,設定寬高屬性並沒有產生什麼作用。對於文章開始的示例圖展示,我們就是在VewPageAndroid元件中新增了5個子View,每一個View中有一個Image用於顯示圖片,和一個可點選的元件並且顯示點選次數。

const styles = StyleSheet.create({
    button: {
        backgroundColor: `#2196f3`,
        borderRadius: 5,
        marginHorizontal: 20,
        marginTop: 10,
        padding: 10,
    },
    buttonText: {
        color: `white`,
    },
    container: {
        flex: 1,
        backgroundColor: `white`,
    },
    image: {
        width: 300,
        height: 200,
        padding: 20,
    },
    viewPager: {
        flex: 1,
    },
});複製程式碼

由於ViewPageAndroid 5頁顯示的內容只是圖片,背景不一樣,其他都是通用的,我們就按如下建立


    render() {
        var pages = []
        for (var i = 0; i < PAGES; i++) {
            var pageStyle = {
                backgroundColor: BGCOLOR[i % BGCOLOR.length],
                alignItems: `center`,
                padding: 20,
            }
            pages.push(
                <View key={i} style={pageStyle} collapsable={false}>
                    <Image
                        style={styles.image}
                        resizeMode={Image.resizeMode.contain}
                        source={IMAGE_URIS[i % BGCOLOR.length]}
                    />
                    <CustomCount/>
                </View>
            )
        }
        return (
            <View style={styles.container}>
                <ViewPagerAndroid
                    style={styles.viewPager}
                    ref={(viewPage) => {
                        this.viewPage = viewPage;
                    }}>
                    {pages}
                </ViewPagerAndroid>
            </View>
        )
    }複製程式碼

用到的圖片資源常量以及背景常量和頁數常量如下

const PAGES = 5;
const BGCOLOR = [`#fdc08e`, `#fff6b9`, `#99d1b7`, `#dde5fe`, `#f79273`];
const IMAGE_URIS = [
    require(`./Thumbnails/cat.png`),
    require(`./Thumbnails/monkey.png`),
    require(`./Thumbnails/rabbit.png`),
    require(`./Thumbnails/tiger.png`),
    require(`./Thumbnails/duck.png`),
];複製程式碼

對於Image元件通過source指定要顯示的圖片,其它屬性使用可以參考之前的文章ReactNative Image元件詳解,CustomCount是定義的一個元件,

class CustomCount extends Component {
    state = {
        count: 1,
    }
    render() {
        return (
            <View>
                <TouchableOpacity
                    activeOpacity={0.5}
                    onPress={() => this.setState({count: this.state.count + 1})}
                    style={{backgroundColor: `#38adff`, borderRadius: 5, marginTop: 20, padding: 10}}
                >
                    <Text>我是可點選的 {this.state.count}</Text>
                </TouchableOpacity>
            </View>)
    }
}複製程式碼

在定義的點選元件中設定一個狀態count,用於顯示點選次數。這樣我們就可以實現看到大致效果了。

設定初始化時顯示頁數

在預設的時候,總是顯示第一頁,很多時候,我們需要顯示指定的頁數,例如我們實現了一個日曆,有12頁(12個月),那我們點選開啟日曆時,要顯示當前月的資訊。如果當前是8月,那麼就要預設顯示第八頁,不需要再我們一頁一頁的翻到該頁,這時候就要使用initialPage 屬性,它可以指定第一個顯示的頁數,該值從0開始。如設定預設顯示第二頁,如下

 initialPage={1}複製程式碼

keyboardDismissMode

如果我們使用了用於輸入的元件,就會彈出軟鍵盤,那麼在拖動翻頁時需要隱藏軟鍵盤,就需要使用此屬性,它有兩個值分別是none(預設值,拖拽不會讓鍵盤消失)和on-drag(當拖拽開始的時候會讓鍵盤消失)。如果我們設定滑動時隱藏軟鍵盤,如下

 keyboardDismissMode="on-drag"複製程式碼

設定每相鄰頁之間的間距

在上面的展示圖中,我們看到每兩個相鄰頁顯示有10畫素的白色間距,這個效果是通過pageMargin屬性設定的,顏色對於間距顯示的的顏色,是ViewPagerAndroid中樣式設定的背景色,如果沒有設定,從它父檢視繼承。如我們設定間距10畫素

pageMargin={10}複製程式碼

scrollEnabled

該屬性是用來設定是否可以滾動支援,當設定true時表示可以滾動翻頁,預設值也是true,如果設定false的話,就表示不可滾動翻頁,如此此時想實現翻頁效果,那就需要使用setPage方法,稍後再介紹其使用。

顯示頁數指示器

在圖例中,我們看到有一個顯示當前頁數以及總頁數的指示器,要實現此功能,我們我們需要用到onPageSelected屬性函式,每當頁面切換完成後,該函式會呼叫,該函式有一個引數event,可以通過event.nativeEvent.position 獲取當前頁面的下標。

//增加屬性
 onPageSelected={this._onPageSelected}

_onPageSelected = (event) => {
        console.log(`_onPageSelected`)
        this.setState({page: event.nativeEvent.position});
    }複製程式碼

我們增加了一個狀態值page用於標示當前頁面的下標。然後在ViewPageAndroid下面新增元件Text,用於顯示當前頁面指示器。

<Text style={[style, {textAlign: `center`}]}>{this.state.page + 1}/{pages.length}</Text>複製程式碼

由於頁面下標從0開始,我們顯示時對其加1。通過上面我們實現了頁面指示器顯示。

很多時候,我們需要在需要在翻頁時實現一些動畫,例如翻頁時Tab的顏色變化動畫,在RN中,我們也可以實現效果,實現此效果時通過onPageScroll屬性函式,當我們拖動頁面時這個函式會一直回撥,該函式有一個引數,我們可以通過event.nativeEvent獲取我們需要的資料。

  • position 從左數起第一個當前可見的頁面的下標。(經過測試這個資料的用處不大,切記這個position和onPageSelected攜帶的position值不一樣,不是當前頁面下標)
  • offset 一個在[0,1)(大於等於0,小於1)之間的範圍,代表當前頁面切換的狀態。值x表示現在”position”所表示的頁有(1 – x)的部分可見,而下一頁有x的部分可見。
    看到了把offset 變化時0到1之間的數值,當向左滑動翻頁時(相當於下一頁)該值時0到1變化,向右滑動翻頁(相當於上一頁)是1到0變化。我們就可以通過該值進行一些類似微信那種透明讀,或者顏色深淺,等我們任何想要實現的動畫。

    onPageScrollStateChanged

    該函式用於監測ViewPageAndroid的狀態,它有三個值

  • idle 空閒,意味著當前沒有互動。

  • dragging 拖動中,意味著當前頁面正在被拖動。
  • settling 處理中,意味著當前頁面發生過互動,且正在結束開頭或收尾的動畫。

我們增加一個狀態scrollState。然後如圖例一樣,將狀態顯示。

 onPageScrollStateChanged={this._onPageScrollStateChanged}

_onPageScrollStateChanged = (state: ViewPagerScrollState) => {
        console.log(`_onPageScrollStateChanged`)
        this.setState({scrollState: state});
    };複製程式碼

使用按鈕實現上下翻頁

在圖例中我們有上一頁和下一頁兩個按鈕。實現此功能可以通過ViewPagerAndroid的setPage方法

    _onPress = (offset) => {
        var goPage = (this.state.page + offset + PAGES) % PAGES
        if (this.state.animationsAreEnabled) {
            this.viewPage.setPage(goPage)
        } else {
            this.viewPage.setPageWithoutAnimation(goPage)
        }
        this.setState({page: goPage})
    }複製程式碼

我將上一頁和下一頁點選事件統一處理了,當點選下一頁時引數傳1,當點選上一頁時引數傳-1。goPage 即使我們對將要跳轉的頁面下標做計算。如果當前是第一頁,再點選上一頁時將跳轉到最後一頁,計算到要跳轉的頁面下標後,呼叫setPage或者setPageWithoutAnimation都可以實現,區別通過名字頁顯而易見。當使用setPage時最後一頁和第一頁相互切換時會有個過度動畫。如果使用setPageWithoutAnimation就沒有動畫。

好了,ViewPageAndroid的相關介紹就到此為止了,想檢視全部原始碼,可前往GitHub,今天的這篇文章就到此結束了,若文中有錯誤的地方歡迎指出,共同進步,謝謝。Have a wonderful day.

相關文章