1
1
/* @flow */
2
2
3
- import React from 'react'
3
+ import React from 'react' ;
4
4
import {
5
5
View ,
6
6
StyleSheet ,
@@ -9,15 +9,15 @@ import {
9
9
Animated ,
10
10
StatusBar ,
11
11
Dimensions
12
- } from 'react-native'
13
- import SkipButton from './template/SkipButton'
14
- import Animations from './animations/Animations'
15
- import { ifIphoneX } from 'react-native-iphone-x-helper'
12
+ } from 'react-native' ;
13
+ import SkipButton from './template/SkipButton' ;
14
+ import Animations from './animations/Animations' ;
15
+ import { ifIphoneX } from 'react-native-iphone-x-helper' ;
16
16
17
- import type { Element } from 'react'
18
- import type { AnimationTypes } from './animations/Animations'
17
+ import type { Element } from 'react' ;
18
+ import type { AnimationTypes } from './animations/Animations' ;
19
19
20
- const SCREEN_WIDTH = Dimensions . get ( 'window' ) . width
20
+ const SCREEN_WIDTH = Dimensions . get ( 'window' ) . width ;
21
21
22
22
type Props = {
23
23
children : any ,
@@ -29,99 +29,123 @@ type Props = {
29
29
skipLastTitleButton ?: string ,
30
30
skipButton ?: Element < * > ,
31
31
customAnimation ?: Object ,
32
- animationType ?: string
33
- }
32
+ animationType ?:
33
+ | 'Parallax'
34
+ | 'Pager'
35
+ | 'ZoomOut'
36
+ | 'FadeIn'
37
+ | 'TranslateY'
38
+ | 'RotateX'
39
+ | 'RotateY'
40
+ | 'Flip' ,
41
+ showSkipButton ?: boolean ,
42
+ tintStatusBar ?: boolean
43
+ } ;
34
44
type State = {
35
45
xOffset : Animated . Value ,
36
46
page : number
37
- }
47
+ } ;
38
48
39
49
class IntroSlider extends React . Component < Props , State > {
40
- scrollView : ScrollView
50
+ scrollView : ScrollView ;
41
51
42
52
static defaultProps = {
43
53
page : 0 ,
44
- animationType : 'Pager'
45
- }
54
+ animationType : 'Pager' ,
55
+ showSkipButton : true ,
56
+ tintStatusBar : true
57
+ } ;
46
58
47
59
constructor ( props : Props ) {
48
- super ( props )
60
+ super ( props ) ;
49
61
this . state = {
50
62
xOffset : new Animated . Value ( 0 ) ,
51
63
page : props . page
52
- }
64
+ } ;
53
65
}
54
66
55
67
componentWillMount ( ) {
56
- const position : number = this . state . page
68
+ const position : number = this . state . page ;
57
69
if ( this . isAndroidStatusBar ( ) && this . props . tintStatusBar ) {
58
70
StatusBar . setBackgroundColor (
59
71
this . shadeStatusBar (
60
72
this . props . children [ position ] . props . backgroundColor ,
61
73
- 0.3
62
74
) ,
63
75
true
64
- )
76
+ ) ;
65
77
}
66
78
}
67
79
68
80
renderDots = ( ) : Element < * > => {
69
- const { activeDotStyle, inactiveDotStyle } = this . props
70
- let dotsArray : Array < * > = [ ]
81
+ const { activeDotStyle, inactiveDotStyle } = this . props ;
82
+ let dotsArray : Array < * > = [ ] ;
71
83
72
84
for ( let index = 0 ; index < this . props . children . length ; index ++ ) {
73
- const isSelected : boolean = this . state . page === index
85
+ const isSelected : boolean = this . state . page === index ;
74
86
dotsArray . push (
75
87
< View
76
88
key = { index }
77
- style = { [ styles . dot , isSelected ? activeDotStyle : inactiveDotStyle ] }
89
+ style = { [
90
+ styles . dot ,
91
+ isSelected
92
+ ? {
93
+ ...styles . active ,
94
+ ...activeDotStyle
95
+ }
96
+ : inactiveDotStyle
97
+ ] }
78
98
/>
79
- )
99
+ ) ;
80
100
}
81
- return < View style = { styles . dotsContainer } > { dotsArray } </ View >
82
- }
101
+ return < View style = { styles . dotsContainer } > { dotsArray } </ View > ;
102
+ } ;
83
103
84
- _getAnimation = ( index : number , animationType : string ) : Function => {
85
- return Animations [ animationType ] ( index , this . state . xOffset )
86
- }
104
+ _getAnimation = ( index : number , animationType : string ) : ?Function => {
105
+ if ( ! Animations [ animationType ] ) {
106
+ return ;
107
+ }
108
+ return Animations [ animationType ] ( index , this . state . xOffset ) ;
109
+ } ;
87
110
88
111
/**
89
112
* Render each child view in the ViewPager
90
113
* @returns {* }
91
114
*/
92
115
renderChildren = ( ) : Array < Element < * >> => {
93
- const { customAnimation } = this . props
94
116
return this . props . children . map ( ( child : Object , index : number ) => {
95
117
return (
96
- < View key = { index } style = { { width : SCREEN_WIDTH } } >
97
- < Animated . View
98
- style = { [
99
- styles . container ,
100
- this . _getAnimation ( index , this . props . animationType ) || customAnimation
101
- ] } >
102
- { child }
103
- </ Animated . View >
118
+ < View
119
+ key = { index }
120
+ style = { {
121
+ width : SCREEN_WIDTH
122
+ } } >
123
+ { React . cloneElement ( child , {
124
+ animation :
125
+ this . props . customAnimation ||
126
+ this . _getAnimation ( index , this . props . animationType )
127
+ } ) }
104
128
</ View >
105
- )
106
- } )
107
- }
129
+ ) ;
130
+ } ) ;
131
+ } ;
108
132
109
133
/**
110
134
* Handles page change event
111
135
* @param e
112
136
*/
113
137
onPageSelected = ( e : Object ) => {
114
138
// Calculate current index
115
- const index = Math . round ( e . nativeEvent . contentOffset . x / SCREEN_WIDTH )
139
+ const index = Math . round ( e . nativeEvent . contentOffset . x / SCREEN_WIDTH ) ;
116
140
117
141
// Only call the function if the index is an integer
118
142
if ( index === parseInt ( index , 10 ) ) {
119
143
if ( index < 0 || index >= React . Children . count ( this . props . children ) ) {
120
- return
144
+ return ;
121
145
}
122
- this . handleBottomStepper ( index )
146
+ this . handleBottomStepper ( index ) ;
123
147
}
124
- }
148
+ } ;
125
149
126
150
/**
127
151
* Handles bottom stepper buttons behaviour
@@ -135,18 +159,18 @@ class IntroSlider extends React.Component<Props, State> {
135
159
- 0.3
136
160
) ,
137
161
false
138
- )
162
+ ) ;
139
163
}
140
- this . setState ( { page : position } )
141
- }
164
+ this . setState ( { page : position } ) ;
165
+ } ;
142
166
143
167
shadeStatusBar = ( color : string , percent : number ) : string => {
144
168
const first = parseInt ( color . slice ( 1 ) , 16 ) ,
145
169
black = first & 0x0000ff ,
146
170
green = ( first >> 8 ) & 0x00ff ,
147
171
percentage = percent < 0 ? percent * - 1 : percent ,
148
172
red = first >> 16 ,
149
- theme = percent < 0 ? 0 : 255
173
+ theme = percent < 0 ? 0 : 255 ;
150
174
151
175
return (
152
176
'#' +
@@ -158,27 +182,27 @@ class IntroSlider extends React.Component<Props, State> {
158
182
)
159
183
. toString ( 16 )
160
184
. slice ( 1 )
161
- )
162
- }
185
+ ) ;
186
+ } ;
163
187
164
188
isAndroidStatusBar = ( ) : boolean => {
165
- return this . props . children . length > 0 && Platform . OS === 'android'
166
- }
189
+ return this . props . children . length > 0 && Platform . OS === 'android' ;
190
+ } ;
167
191
168
192
render ( ) {
169
- const isLast : boolean = this . props . children . length - 1 === this . state . page
193
+ const isLast : boolean = this . props . children . length - 1 === this . state . page ;
170
194
return (
171
195
< View style = { styles . container } >
172
196
< Animated . ScrollView
173
197
ref = { ( ref : any ) => {
174
- this . scrollView = ref
198
+ this . scrollView = ref ;
175
199
} }
176
200
style = { styles . container }
177
201
horizontal = { true }
178
202
pagingEnabled = { true }
179
203
removeClippedSubviews = { true }
180
204
directionalLockEnabled = { true }
181
- scrollEventThrottle = { 1 }
205
+ scrollEventThrottle = { 10 }
182
206
bounces = { false }
183
207
scrollsToTop = { false }
184
208
automaticallyAdjustContentInsets = { false }
@@ -188,7 +212,9 @@ class IntroSlider extends React.Component<Props, State> {
188
212
[
189
213
{
190
214
nativeEvent : {
191
- contentOffset : { x : this . state . xOffset }
215
+ contentOffset : {
216
+ x : this . state . xOffset
217
+ }
192
218
}
193
219
}
194
220
] ,
@@ -204,7 +230,9 @@ class IntroSlider extends React.Component<Props, State> {
204
230
< SkipButton
205
231
onSkip = { this . props . onSkip }
206
232
skipTitleButton = {
207
- isLast ? this . props . skipLastTitleButton : this . props . skipTitleButton
233
+ isLast
234
+ ? this . props . skipLastTitleButton
235
+ : this . props . skipTitleButton
208
236
}
209
237
/>
210
238
) : (
@@ -213,7 +241,7 @@ class IntroSlider extends React.Component<Props, State> {
213
241
{ this . renderDots ( ) }
214
242
</ View >
215
243
</ View >
216
- )
244
+ ) ;
217
245
}
218
246
}
219
247
@@ -223,15 +251,14 @@ const styles = StyleSheet.create({
223
251
overflow : 'hidden'
224
252
} ,
225
253
bottom : {
226
- bottom : 12 ,
254
+ bottom : 30 ,
227
255
...ifIphoneX ( {
228
256
bottom : 40
229
257
} )
230
258
} ,
231
259
dotsContainer : {
232
260
flexDirection : 'row' ,
233
261
justifyContent : 'center' ,
234
- bottom : 5 ,
235
262
position : 'absolute' ,
236
263
alignItems : 'center' ,
237
264
justifyContent : 'center' ,
@@ -244,7 +271,10 @@ const styles = StyleSheet.create({
244
271
borderRadius : 20 ,
245
272
backgroundColor : 'rgba(0, 0, 0, .2)' ,
246
273
marginHorizontal : 5
274
+ } ,
275
+ active : {
276
+ backgroundColor : 'white'
247
277
}
248
- } )
278
+ } ) ;
249
279
250
- export default IntroSlider
280
+ export default IntroSlider ;
0 commit comments