ReactNative ViewPageAndroid组件详解

作者: Code4Android | 来源:发表于2017-08-20 21:39 被阅读393次

    源码传送门

    在我们开发Android的时候,ViewPage这个控件的使用频率还是很高的,最简单的就是制作引导页,应用程序的主界面等,在ReactNative开发中实现该功能的组件是ViewPageAndroid,当你看到该组件是以Android结尾,你就明白该组件只对Android平台有效,如果使用就要考虑适配iOS(目前学习到的ScrollView组件可以实现此效果,具体实现不在本篇文章介绍),今天就通过下面示例图,介绍ViewPageAndroid的API以及使用。


    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.

    相关文章

      网友评论

        本文标题:ReactNative ViewPageAndroid组件详解

        本文链接:https://www.haomeiwen.com/subject/nrffdxtx.html