UNPKG

react-native-ui-lib

Version:

UI Components Library for React Native ###### Lateset version support RN44

123 lines (106 loc) 2.89 kB
import React, {PropTypes} from 'react'; import {ScrollView, StyleSheet} from 'react-native'; import _ from 'lodash'; import {BaseComponent} from '../../commons'; import View from '../view'; import {Constants} from '../../helpers'; import * as presenter from './CarouselPresenter'; /** * Carousel for scrolling pages horizontally */ export default class Carousel extends BaseComponent { static displayName = 'Carousel'; static propTypes = { initialPage: PropTypes.number, pageWidth: PropTypes.number, onChangePage: PropTypes.func, containerStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.number, PropTypes.array]), }; static defaultProps = { initialPage: 0, pageWidth: Constants.screenWidth, } constructor(props) { super(props); this.state = { currentPage: props.initialPage, }; this.onScroll = this.onScroll.bind(this); this.updateOffset = this.updateOffset.bind(this); } generateStyles() { this.styles = createStyles(this.props); } onScroll(event) { const offsetX = event.nativeEvent.contentOffset.x; if (offsetX >= 0) { const {currentPage} = this.state; const newPage = presenter.calcPageIndex(offsetX, this.props); this.setState({ currentPage: newPage, }, () => { if (currentPage !== newPage) { _.invoke(this.props, 'onChangePage', newPage, currentPage); } }); if (presenter.isOutOfBounds(offsetX, this.props)) { this.updateOffset(); } } } updateOffset(animated = false) { const x = presenter.calcOffset(this.props, this.state); this.carousel.scrollTo({x, animated}); } componentDidMount() { setTimeout(() => { this.updateOffset(); }, Constants.isIOS ? 0 : 50); } cloneChild(child) { if (!child.key) { return child; } return React.cloneElement(child, { key: `${child.key}-clone`, }); } renderChildren() { const {children} = this.props; const length = presenter.getChildrenLength(this.props); return [ this.cloneChild(children[length - 1]), ...children, this.cloneChild(children[0]), ]; } render() { const {containerStyle} = this.props; return ( <View flex style={containerStyle}> <ScrollView ref={(scrollView) => { this.carousel = scrollView; }} horizontal showsHorizontalScrollIndicator={false} pagingEnabled onScroll={this.onScroll} scrollEventThrottle={200} > {this.renderChildren()} </ScrollView> </View> ); } goToPage(pageIndex, animated = true) { this.setState({ currentPage: pageIndex, }, () => this.updateOffset(animated)); } } function createStyles() { return StyleSheet.create({ // container: { // flex: 1, // }, }); }