美文网首页
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