美文网首页
React-Native ViewPagerAndroid使用

React-Native ViewPagerAndroid使用

作者: Android_冯星 | 来源:发表于2018-08-24 10:38 被阅读0次

    效果


    small.gif

    代码

    入口
    'use strict';
    import React, {
        Component
    } from 'react';
    
    import {
        AppRegistry,
        StyleSheet,
        Text,
        View,
        Button,
        PixelRatio,
        ViewPagerAndroid,
        Image,
        TouchableOpacity,
    } from 'react-native';
    
    import {
        createStackNavigator
    } from 'react-navigation';
    
    import CustomButton from './CustomButton';
    import ProgressBar from './ProgressBar';
    import Likes from './Likes';
    import HomeUi from './HomeUi';
    //页面数量
    const PAGES = 5;
    //背景颜色
    const PAGE_BG_COLORS = ['#fdc08e', '#fff6b9', '#99d1b7', '#dde5fe', '#f79273'];
    //图片地址
    const PAGE_IMAGES = [
        'http://img06.tooopen.com/images/20161121/tooopen_sy_187362418112.jpg',
        'http://a.hiphotos.baidu.com/image/h%3D300/sign=4f5477ac8f26cffc762ab9b289014a7d/b3fb43166d224f4ad8b5722604f790529822d1d3.jpg',
        'http://a.hiphotos.baidu.com/image/h%3D300/sign=10b374237f0e0cf3bff748fb3a47f23d/adaf2edda3cc7cd90df1ede83401213fb80e9127.jpg',
        'http://e.hiphotos.baidu.com/image/h%3D300/sign=8562b2c234dbb6fd3a5be3263925aba6/8ad4b31c8701a18b536e1476932f07082838fe06.jpg',
        'http://a.hiphotos.baidu.com/image/h%3D300/sign=fbe3d9666ed9f2d33f1122ef99ed8a53/3bf33a87e950352a464bc38f5f43fbf2b2118b0b.jpg'
    ];
    
    
    class WelcomeUi extends Component {
    
        constructor(props) {
            super(props);
            //定义属性
            this.state = {
           //当前页面
                page: 0,
                animationsAreEnabled: true, //动画是否开启
            //进度条使用 position当前页面 offset偏移量
                progress: {
                    position: 0,
                    offset: 0,
                },
            }
        }
    
    
        /**
            当在页间切换时(不论是由于动画还是由于用户在页间滑动/拖拽)执行。
            
            回调参数中的 event.nativeEvent 对象会包含如下数据:
            
            position 从左数起第一个当前可见的页面的下标。
            offset 一个在[0,1]之内的范围(可以等于0或1),代表当前页面切换的状态。值 x 表示现在"position"所表示的页有(1 - x)的部分可见,而下一页有 x 的部分可见。
    
        ViewPager滑动时就会回调此方法,然后改变属性,视图就会不断刷新
        */
        onPageScroll = (event) => {
            console.log(event.nativeEvent);
            this.setState({
                progress: event.nativeEvent
            });
        }
    
        /**
        *   
            这个回调会在页面切换完成后(当用户在页面间滑动)调用。
    
            回调参数中的 event.nativeEvent 对象会包含如下的字段:
    
            position 当前被选中的页面下标
    
           此方法当ViewPager完全显示时被调用 setState设置属性 改变视图刷新   setState是异步的 下面会有说明。
        */
        onPageSelected = (event) => {
            console.log(event.nativeEvent);
            this.setState({
                page: event.nativeEvent.position,
            });
        }
    
    /**
    *  跳到指定的页面 参数page 第几个页面
      this.viewPager使用ref属性。详细请见ViewPageAndroid中的ref属性,也可以看看我写的ref属性这篇文章。
    setPage是ViewPagerAndroid中的方法。跳到指定页面(带动画)
    setPageWithoutAnimation和setPage方法类似,(不带动画)
    最后对page属性赋值,刷新视图。
    */
        go = (page) => {
            if (this.state.animationsAreEnabled) {
                this.viewPager.setPage(page);
            } else {
                this.viewPager.setPageWithoutAnimation(page);
            }
            console.log('go : ' + page);
            this.setState({
                page
            });
            //这里取到的page没有更新掉  但是render中更新了。 难道是因为 setState更新是异步的?
            console.log('go page : ' + this.state.page);
        }
    
    
    /**
    *这个方法和go方法类似 可以优化下代码,我没有优化的原因是因为这个写法报错了,改完之后 没有改回去,一样用
    
    优化:
    move = (page) => {
            var current = this.state.page + page;
            this.go(current);
    }
    */
        move = (page) => {
    
            //      let currentPage = this.state.page + page;
            //      console.log('move : ' + page + 'currentPage : ' + currentPage);
            //      this.go(currentPage);
            let currentPage = this.state.page + page
            if (this.state.animationsAreEnabled) {
                this.viewPager.setPage(currentPage);
            } else {
                this.viewPager.setPageWithoutAnimation(currentPage);
            }
            console.log('move : ' + currentPage);
            this.setState({
                page: currentPage
            }, () => {
                console.log('改进写法:' + this.state.page);
            });
    
            //这里取到的page没有更新掉  但是render中更新了。 难道是因为 setState更新是异步的? 然后搜了一下 确实是异步的 在setState的第二个参数获取最新的值
    
            /**
            this.setState({
            page:'123456',
            }, () => {
            console.log(this.state.page); 
            })
            */
    
            console.log('move page : ' + this.state.page);
    
        }
    
    
        render() {
    //点赞的小图标
            const thunbsUp = "\uD83D\uDC4D";
    //需要显示的页面数组 里面存放的都是组件
            var pages = [];
    //循环
            for (var i = 0; i < PAGES; i++) {
    //写页面样式 因为背景颜色不一样 动态生成
                var pagerStyle = {
                    backgroundColor: PAGE_BG_COLORS[i % PAGE_BG_COLORS.length],
                    alignItems: 'center',
                    padding: 20,
                }
                //除去最有一个页面
                if (i < PAGES - 1) {
                    //collapsable 如果一个View只用于布局它的子组件,
                    // 则它可能会为了优化而从原生布局树中移除。 把此属性设为false可以禁用这个优化,以确保对应视图在原生结构中存在。
                    pages.push(
                        <View style={pagerStyle} key={i} collapsable={false}>
                            <Image
                                style={styles.images}
                                source={{uri:PAGE_IMAGES[i]}}
                            />
                            <Likes></Likes>
                        </View>
                    );
                } else { //最后一个页面
                    pages.push(
                        <View style={pagerStyle} key={i} collapsable={false}>
                            <Image
                                style={styles.images}
                                source={{uri:PAGE_IMAGES[i]}}
                            />
                            <Likes/>
                            <TouchableOpacity style={styles.startupButtpn} onPress={()=>this.props.navigation.navigate('Home')}>
                                <Text style={styles.likesText}>{thunbsUp+'启动首页'}</Text>
                            </TouchableOpacity>
                        </View>
                    );
                }
            }
    
            var {
                page,
                animationsAreEnabled
            } = this.state;
            console.log('render page : ' + page);
            return (
                <View style={styles.container}>
                    <ViewPagerAndroid
                        style={styles.viewpager}
                        //初始选中的页的下标。你可以用 setPage 函数来翻页,并且用 onPageSelected 来监听页的变化。
                        initialPage={0}
                        onPageScroll={this.onPageScroll}
                        onPageSelected={this.onPageSelected}
                        ref={viewPager=>{this.viewPager=viewPager;}}
                    >
                    {pages}
                    </ViewPagerAndroid>
    
                    <View style={styles.buttons}>
                    {
                        animationsAreEnabled?
                        <CustomButton
                            text='Turn off animations'
                            enable={true}
                            onPress={()=>this.setState({animationsAreEnabled:false})}
                        />
                        :
                        <CustomButton
                            text='Turn off animations back on'
                            enable={true}
                            onPress={()=>this.setState({animationsAreEnabled:true})}
                        />
                    }
                    
                    </View>
                    <View style={styles.buttons}>
                        <CustomButton text='Start' enable={page>0} onPress={()=>this.go(0)}/>
                        <CustomButton text='Prev' enable={page>0} onPress={()=>this.move(-1)}/>
                        <ProgressBar progress={this.state.progress} size={100} length={PAGES}></ProgressBar>
                        <CustomButton text='Next' enable={page<PAGES-1} onPress={()=>this.move(1)}/>
                        <CustomButton text='Last' enable={page<PAGES-1} onPress={()=>this.go(PAGES-1)}/>
                    </View>
                </View>
            );
        }
    }
    
    class Home extends Component {
        render() {
            return (
                <View style={styles.containerHome}>
                    <Text style={styles.welcomeHome}>'我是冯星'</Text>
                </View>
            );
        }
    }
    
    
    const RootNavigation = createStackNavigator({
        WelcomeUi: {
            screen: WelcomeUi,
        },
        Home: {
            screen: Home,
        },
    }, {
        headerMode: 'none',
    });
    
    const styles = StyleSheet.create({
        container: {
            flex: 1,
        },
        viewpager: {
            flex: 1,
        },
        images: {
            width: 200,
            height: 200,
            padding: 20,
        },
        pagerStyle: {
            backgroundColor: '#fff6b9',
            alignItems: 'center',
            padding: 20,
        },
        buttons: {
            flexDirection: 'row',
            height: 30,
            backgroundColor: 'black',
            alignItems: 'center',
            justifyContent: 'space-between',
        },
        startupButtpn: {
            backgroundColor: 'rgba(0,0,0,0.1)',
            borderColor: '#333333',
            borderWidth: 1 / PixelRatio.get(),
            borderRadius: 5,
            margin: 8,
            padding: 8,
        },
        likesText: {
            fontSize: 18,
            alignSelf: 'center',
        },
        containerHome: {
            flex: 1,
            justifyContent: 'center',
            alignItems: 'center',
            backgroundColor: '#F5FCFF',
        },
        welcomeHome: {
            fontSize: 20,
            textAlign: 'center',
            margin: 10,
        },
    });
    
    AppRegistry.registerComponent('MyApp', () => RootNavigation);
    
    自定义按钮组件
    import React, {
        Component
    } from 'react';
    
    import {
        StyleSheet,
        Text,
        TouchableWithoutFeedback,
        TouchableHighlight,
        View,
        Image,
        PixelRatio,
    } from 'react-native';
    
    export default class CustomButton extends Component {
    
        //传递的属性 {text: "Turn off animations", enable: true, onPress: ƒ}
    
        constructor(props) {
            super(props);
            console.log(props);
        }
    
        _handlerOnPress = () => {
    //如果按钮可以使用 并且 传递过来的onPress有值 就执行onPress函数
            if (this.props.enable && this.props.onPress) {
                this.props.onPress();
            }
        }
    
        render() {
            return (
                <TouchableWithoutFeedback onPress={this._handlerOnPress}>
                    <View style={[styles.button,this.props.enable?{}:styles.buttonDisabled]}>
                        <Text style={styles.buttonText}>{this.props.text}</Text>
                    </View>     
                </TouchableWithoutFeedback>
            );
        }
    }
    
    const styles = StyleSheet.create({
        button: {
            flex: 1,
            width: 0,
            margin: 5,
            borderColor: 'red',
            borderWidth: 1 / PixelRatio.get(),
            backgroundColor: 'gray',
            borderRadius: 3,
        },
        buttonDisabled: {
            backgroundColor: 'yellow',
            opacity: 0.5,
        },
        buttonText: {
            color: 'white',
            textAlign: 'center',
        },
    })
    
    喜欢个数组件
    import React, {
        Component
    } from 'react';
    import {
        StyleSheet,
        Text,
        View,
        TouchableOpacity,
        PixelRatio,
    } from 'react-native';
    
    //rn 最小单位
    var ptOne = 1 / PixelRatio.get();
    
    export default class Likes extends Component {
    
        constructor(props) {
            super(props);
            this.state = {
                likes: 0,
            }
        }
    
    //点击组件 +1刷新显示。
        onClick = () => {
            var a = this.state.likes;
            this.setState({
                likes: this.state.likes + 1,
            });
        }
    
        render() {
            //这是一个点赞的小图标 一个代码就搞定了
            const thunbsUp = '\uD83D\uDC4D';
            return (
                <View style={styles.container}>
                    <TouchableOpacity style={styles.buttonLikes} onPress={this.onClick}>
                        <Text>{thunbsUp+'Like'}</Text>
                    </TouchableOpacity>
                    <Text style={styles.likesText}>{this.state.likes+'个喜欢数'}</Text>
                </View>
            );
        }
    }
    const styles = StyleSheet.create({
        buttonLikes: {
            borderWidth: ptOne,
            borderColor: 'rgba(0,0,0,0.1)',
            backgroundColor: '#cccccc',
            borderRadius: 5,
            margin: 5,
            padding: 5,
        },
        container: {
            flexDirection: 'row',
        },
        likesText: {
            fontSize: 16,
            alignSelf: 'center',
        },
    });
    
    进度条组件
    import React, {
        Component
    } from 'react';
    
    import {
        StyleSheet,
        View,
    } from 'react-native';
    
    export default class ProgressBar extends Component {
    
        //props内部参数 {length:5,Size:100,progress:{position:0,offset:0}}
        constructor(props) {
            super(props);
        }
    
        render() {
    //进度条的实现是两个view。给view设置width属性 来改变进度。
    //根据当前页面和偏移量计算出view的宽是多少
            console.log(this.props);
            var fractionalPosition = (this.props.progress.position + this.props.progress.offset);
            var progressBarSize = (fractionalPosition / (this.props.length - 1)) * this.props.size;
            return (
                <View style={[styles.progressBarContainer,{width:this.props.size}]}>
                    <View style={[styles.progressBar,{width:progressBarSize}]}></View>
                </View>
            );
        }
    }
    
    const styles = StyleSheet.create({
        progressBarContainer: {
            height: 10,
            margin: 10,
            borderColor: '#eeeeee',
            borderWidth: 2,
        },
        progressBar: {
            alignSelf: 'flex-start',
            flex: 1,
            backgroundColor: '#ff0000',
        }
    });
    

    相关文章

      网友评论

          本文标题:React-Native ViewPagerAndroid使用

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