1 | import React, { Component } from 'react';
|
2 | import { Dimensions, Platform, ScrollView, View, } from 'react-native';
|
3 | export class PageSlider extends Component {
|
4 | constructor(props) {
|
5 | super(props);
|
6 | this.offsetX = 0;
|
7 | this.hasDoneInitialScroll = false;
|
8 | this.scrollView = null;
|
9 | this.onContentSizeChange = (width, height) => {
|
10 | if (Platform.OS === 'android' &&
|
11 | width &&
|
12 | height &&
|
13 | this.initialSelectedPage &&
|
14 | !this.hasDoneInitialScroll) {
|
15 | this.scrollToPage(this.initialSelectedPage, false);
|
16 | this.hasDoneInitialScroll = true;
|
17 | }
|
18 | };
|
19 | this.onScroll = (e) => {
|
20 | this.offsetX = e.nativeEvent.contentOffset.x;
|
21 | const currentPage = this.getCurrentPage();
|
22 | this.props.onCurrentPageChange(currentPage);
|
23 | };
|
24 | this.onMomentumScrollEnd = () => {
|
25 | const currentPage = this.getCurrentPage();
|
26 | if (this.props.selectedPage !== currentPage) {
|
27 | this.props.onSelectedPageChange(currentPage);
|
28 | }
|
29 | };
|
30 |
|
31 | this.getPageWidth = () => {
|
32 | const { width } = Dimensions.get('screen');
|
33 | if (this.props.mode === 'page') {
|
34 | return width;
|
35 | }
|
36 | const { peek, pageMargin } = this.props;
|
37 | return width - 2 * peek + 2 * pageMargin;
|
38 | };
|
39 |
|
40 | this.getCurrentPage = () => {
|
41 | const pageWidth = this.getPageWidth();
|
42 | return Math.floor(this.offsetX / pageWidth - 0.5) + 1;
|
43 | };
|
44 |
|
45 | this.scrollToPage = (index, animated = true) => {
|
46 | var _a;
|
47 | const pageWidth = this.getPageWidth();
|
48 | (_a = this.scrollView) === null || _a === void 0 ? void 0 : _a.scrollTo({ y: 0, x: index * pageWidth, animated });
|
49 | };
|
50 |
|
51 | this.initialSelectedPage = this.props.selectedPage;
|
52 | }
|
53 | componentDidMount() {
|
54 | if (Platform.OS === 'ios' && this.props.selectedPage) {
|
55 |
|
56 | this.scrollToPage(this.props.selectedPage, false);
|
57 | }
|
58 | }
|
59 | componentDidUpdate(prevProps) {
|
60 | const currentPage = this.getCurrentPage();
|
61 | if (prevProps.selectedPage !== this.props.selectedPage &&
|
62 | this.props.selectedPage !== currentPage &&
|
63 | this.props.selectedPage !== undefined) {
|
64 | this.scrollToPage(this.props.selectedPage);
|
65 | }
|
66 | }
|
67 | render() {
|
68 | const { children, mode, style } = this.props;
|
69 | const { width } = Dimensions.get('screen');
|
70 | const pageStyle = {
|
71 | height: '100%',
|
72 | };
|
73 | let scrollViewProps = {};
|
74 |
|
75 | if (mode === 'page') {
|
76 | Object.assign(pageStyle, {
|
77 | width,
|
78 | });
|
79 | }
|
80 | else if (mode === 'card') {
|
81 | const { contentPaddingVertical, peek, pageMargin } = this.props;
|
82 | scrollViewProps = {
|
83 | contentContainerStyle: {
|
84 | paddingHorizontal: peek - pageMargin,
|
85 | paddingVertical: contentPaddingVertical,
|
86 | },
|
87 | decelerationRate: 'fast',
|
88 | snapToAlignment: 'start',
|
89 | snapToInterval: this.getPageWidth(),
|
90 | };
|
91 | if (Platform.OS === 'ios') {
|
92 | |
93 |
|
94 |
|
95 |
|
96 | scrollViewProps.pagingEnabled = false;
|
97 | }
|
98 | Object.assign(pageStyle, {
|
99 | marginHorizontal: pageMargin,
|
100 | width: width - 2 * peek,
|
101 | });
|
102 | }
|
103 |
|
104 | const pages = React.Children.map(children, (page) => {
|
105 |
|
106 | if (!React.isValidElement(page)) {
|
107 | return null;
|
108 | }
|
109 | return (<View key={page.key} style={pageStyle}>
|
110 | {page}
|
111 | </View>);
|
112 | });
|
113 | return (<ScrollView style={style} ref={(scrollView) => {
|
114 | this.scrollView = scrollView;
|
115 | }} horizontal pagingEnabled showsHorizontalScrollIndicator={false} onContentSizeChange={this.onContentSizeChange} onScroll={this.onScroll} onMomentumScrollEnd={this.onMomentumScrollEnd} scrollEventThrottle={8} {...scrollViewProps}>
|
116 | {pages}
|
117 | </ScrollView>);
|
118 | }
|
119 | }
|
120 | PageSlider.defaultProps = {
|
121 | mode: 'page',
|
122 | pageMargin: 8,
|
123 | peek: 24,
|
124 | };
|