美文网首页
react-native ViewPager 无限循环

react-native ViewPager 无限循环

作者: lesliefang | 来源:发表于2017-03-22 13:08 被阅读2921次

    android 用 ViewPagerAndroid 实现
    ios 用 ScrollView 实现
    原生开发在 android 和 ios 中也都是这么做
    原理都一样 : 3 1 2 3 1
    本来 3 个图 1 2 3,在最前面多添加最后一张图 3,在最后面多添加第一张图 1。当滑到最后一张图 1 时跳转到第一张图 1,当滑到第一张图 3 时跳转到倒数第二个图 3。 默认选中第一张图 1。

    viewpager.android.js

    import React, {Component} from "react";
    import {StyleSheet, View, ViewPagerAndroid, Dimensions, Image} from "react-native";
    
    const screenWidth = Dimensions.get('window').width;
    
    /**
     * @author leslie.fang
     * @date 2017-03-22
     */
    export default class ViewPager extends Component {
        constructor(props) {
            super(props);
            this._renderPagers = this._renderPagers.bind(this);
            this._renderCircles = this._renderCircles.bind(this);
            this._onPageSelected = this._onPageSelected.bind(this);
            this.state = {
                currentPage: 0
            };
        }
    
        render() {
            const height = this.props.height || 170;
            return (
                <View>
                    <ViewPagerAndroid
                        initialPage={1}
                        style={{height: height}}
                        ref={viewPager => { this.viewPager = viewPager;  }}
                        onPageSelected={this._onPageSelected}
                    >
                        {this._renderPagers()}
                    </ViewPagerAndroid>
                    {this._renderCircles()}
                </View>
            );
        }
    
        _renderPagers() {
            const imageUrls = this.props.imageUrls;
            if (imageUrls == null || imageUrls.length == 0) {
                return null;
            }
    
            let len = imageUrls.length;
            let pagers = [];
    
            if (len == 1) {
                pagers.push(this._renderPagerItem(imageUrls[0], 0));
            } else {
                // 最后一页插入到第 0 个位置
                pagers.push(this._renderPagerItem(imageUrls[len - 1], 0));
                for (let i = 0; i < len; i++) {
                    pagers.push(this._renderPagerItem(imageUrls[i], i + 1))
                }
                // 第 0 页插入到最后一个位置
                pagers.push(this._renderPagerItem(imageUrls[0], len + 1));
            }
    
            return pagers;
        }
    
        _renderPagerItem(url, key) {
            return (
                <View key={key} style={{flex:1,flexDirection:'row'}}>
                    <Image source={{uri:url}} style={styles.image}/>
                </View>
            );
        }
    
        _renderCircles() {
            const imageUrls = this.props.imageUrls;
            if (imageUrls == null || imageUrls.length <= 1) {
                return null;
            }
    
            let len = imageUrls.length;
            let circles = [];
            for (let i = 0; i < len; i++) {
                let style = styles.circle;
                if (this.state.currentPage == i) {
                    style = [styles.circle, styles.circleSelected];
                }
                circles.push((<View style={style} key={i}/>));
            }
    
            return (
                <View style={styles.circleContainer}>
                    {circles}
                </View>
            );
        }
    
        _onPageSelected(e) {
            const len = this.props.imageUrls.length;
            if (len == 1) {
                return;
            }
    
            let position = e.nativeEvent.position;
            let currentPage;
            if (position == 0) {
                // 当到第 0 页时跳转到倒数第二页
                currentPage = len - 1;
                this.viewPager.setPageWithoutAnimation(len);
            } else if (position == len + 1) {
                // 当到最后一页时跳转到第一页
                currentPage = 0;
                this.viewPager.setPageWithoutAnimation(1);
            } else {
                currentPage = position - 1;
            }
    
            this.setState({
                currentPage: currentPage
            });
        }
    }
    
    ViewPager.propTypes = {
        imageUrls: React.PropTypes.arrayOf(React.PropTypes.string).isRequired,
        height: React.PropTypes.number
    };
    
    const styles = StyleSheet.create({
        image: {
            width: screenWidth,
        },
        circleContainer: {
            position: 'absolute',
            width: '100%',
            bottom: 10,
            flexDirection: 'row',
            justifyContent: 'center',
        },
        circle: {
            width: 10,
            height: 10,
            borderRadius: 5,
            backgroundColor: '#fff',
            marginHorizontal: 5
        },
        circleSelected: {
            backgroundColor: '#0f0'
        }
    });
    

    viewpager.ios.js

    import React, {Component} from "react";
    import {ScrollView, Image, View, Dimensions, StyleSheet} from "react-native";
    
    const screenWidth = Dimensions.get('window').width;
    
    /**
     * @author leslie.fang
     * @date 2017-03-22
     */
    export default class ViewPager extends Component {
        constructor(props) {
            super(props);
            this._renderPagers = this._renderPagers.bind(this);
            this._handleScroll = this._handleScroll.bind(this);
            this.state = {
                currentPage: 0
            };
        }
    
        render() {
            const height = this.props.height || 170;
            return (
                <View style={{height:height}}>
                    <ScrollView
                        ref={(scrollView) => this._scrollView = scrollView}
                        horizontal={true}
                        pagingEnabled={true}
                        showsHorizontalScrollIndicator={false}
                        onMomentumScrollEnd={this._handleScroll}
                    >
                        {this._renderPagers()}
                    </ScrollView>
    
                    {this._renderCircles()}
                </View>
            );
        }
    
        _renderPagers() {
            const imageUrls = this.props.imageUrls;
            if (imageUrls == null || imageUrls.length == 0) {
                return null;
            }
    
            let len = imageUrls.length;
            let pagers = [];
    
            if (len == 1) {
                pagers.push(this._renderPagerItem(imageUrls[0], 0));
            } else {
                // 最后一页插入到第 0 个位置
                pagers.push(this._renderPagerItem(imageUrls[len - 1], 0));
                for (let i = 0; i < len; i++) {
                    pagers.push(this._renderPagerItem(imageUrls[i], i + 1))
                }
                // 第 0 页插入到最后一个位置
                pagers.push(this._renderPagerItem(imageUrls[0], len + 1));
            }
    
            return pagers;
        }
    
        _renderPagerItem(url, key) {
            return (
                <View key={key} style={{flex:1,flexDirection:'row'}}>
                    <Image source={{uri:url}} style={styles.image}/>
                </View>
            );
        }
    
        _renderCircles() {
            const imageUrls = this.props.imageUrls;
            if (imageUrls == null || imageUrls.length <= 1) {
                return null;
            }
    
            let len = imageUrls.length;
            let circles = [];
            for (let i = 0; i < len; i++) {
                let style = styles.circle;
                if (this.state.currentPage == i) {
                    style = [styles.circle, styles.circleSelected];
                }
                circles.push((<View style={style} key={i}/>));
            }
    
            return (
                <View style={styles.circleContainer}>
                    {circles}
                </View>
            );
        }
    
        componentDidMount() {
            let len = this.props.imageUrls.length;
            if (len > 1) {
                // 默认跳到第一页
                this._scrollView.scrollTo({x: screenWidth, y: 0, animated: false});
            }
        }
    
        _handleScroll(e) {
            const len = this.props.imageUrls.length;
            if (len <= 1) {
                return;
            }
    
            let offSet = e.nativeEvent.contentOffset.x;
            let position = Math.floor(offSet / screenWidth);
    
            let currentPage;
            if (position == 0) {
                // 当到第 0 页时跳转到倒数第二页
                currentPage = len - 1;
                this._scrollView.scrollTo({x: len * screenWidth, y: 0, animated: false});
            } else if (position == len + 1) {
                // 当到最后一页时跳转到第一页
                currentPage = 0;
                this._scrollView.scrollTo({x: screenWidth, y: 0, animated: false});
            } else {
                currentPage = position - 1;
            }
    
            this.setState({
                currentPage: currentPage
            });
        }
    }
    
    ViewPager.propTypes = {
        imageUrls: React.PropTypes.arrayOf(React.PropTypes.string).isRequired,
        height: React.PropTypes.number
    };
    
    const styles = StyleSheet.create({
        image: {
            width: screenWidth,
        },
        circleContainer: {
            position: 'absolute',
            width: '100%',
            bottom: 10,
            flexDirection: 'row',
            justifyContent: 'center',
        },
        circle: {
            width: 10,
            height: 10,
            borderRadius: 5,
            backgroundColor: '#fff',
            marginHorizontal: 5
        },
        circleSelected: {
            backgroundColor: '#0f0'
        }
    });
    

    使用

    import ViewPager from './viewpager';
    
    const imageUrls = ['https://dn-mhke0kuv.qbox.me/cf7d3b648376e34a2d9a.jpg', 'https://dn-mhke0kuv.qbox.me/acc12bcff6bad4a12310.jpg', 'https://dn-mhke0kuv.qbox.me/586e632146644e0c3ecd.png'];
    
    const App = React.createClass({
        render: function () {
            return (
                <ViewPager imageUrls={imageUrls}/>
            );
        }
    });
    

    DEMO: https://github.com/lesliebeijing/RNViewPager

    原理上讲 android 中用 ScrollView 实现也是可以的,但总有点问题,所以用了 ViewPagerAndroid 。

    相关文章

      网友评论

          本文标题:react-native ViewPager 无限循环

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