@@ -2,6 +2,7 @@ import React, { Component } from 'react';
2
2
import {
3
3
Animated ,
4
4
Dimensions ,
5
+ Platform ,
5
6
ScrollView ,
6
7
View ,
7
8
ViewPropTypes ,
@@ -45,6 +46,7 @@ const IPropTypes = {
45
46
renderStickyHeader : func ,
46
47
stickyHeaderHeight : number ,
47
48
contentContainerStyle : ViewPropTypes . style ,
49
+ scrollingStickyHeader : bool ,
48
50
} ;
49
51
50
52
class ParallaxScrollView extends Component {
@@ -59,7 +61,7 @@ class ParallaxScrollView extends Component {
59
61
this . state = {
60
62
scrollY : new Animated . Value ( 0 ) ,
61
63
viewHeight : window . height ,
62
- viewWidth : window . width
64
+ viewWidth : window . width ,
63
65
} ;
64
66
this . _footerComponent = { setNativeProps ( ) { } } ; // Initial stub
65
67
this . _footerHeight = 0 ;
@@ -83,19 +85,20 @@ class ParallaxScrollView extends Component {
83
85
stickyHeaderHeight,
84
86
style,
85
87
contentContainerStyle,
88
+ scrollingStickyHeader,
86
89
...scrollViewProps
87
90
} = this . props ;
88
91
89
92
const background = this . _renderBackground ( { fadeOutBackground, backgroundScrollSpeed, backgroundColor, parallaxHeaderHeight, stickyHeaderHeight, renderBackground } ) ;
90
93
const foreground = this . _renderForeground ( { fadeOutForeground, parallaxHeaderHeight, stickyHeaderHeight, renderForeground : renderForeground || renderParallaxHeader } ) ;
91
94
const bodyComponent = this . _wrapChildren ( children , { contentBackgroundColor, stickyHeaderHeight, contentContainerStyle } ) ;
92
95
const footerSpacer = this . _renderFooterSpacer ( { contentBackgroundColor } ) ;
93
- const maybeStickyHeader = this . _maybeRenderStickyHeader ( { parallaxHeaderHeight, stickyHeaderHeight, backgroundColor, renderFixedHeader, renderStickyHeader } ) ;
96
+ const maybeStickyHeader = this . _maybeRenderStickyHeader ( { parallaxHeaderHeight, stickyHeaderHeight, backgroundColor, renderFixedHeader, renderStickyHeader, scrollingStickyHeader } ) ;
94
97
const scrollElement = renderScrollComponent ( scrollViewProps ) ;
95
98
96
99
return (
97
- < View style = { [ style , styles . container ] }
98
- onLayout = { ( e ) => this . _maybeUpdateViewDimensions ( e ) } >
100
+ < View style = { [ style , styles . container ] }
101
+ onLayout = { ( e ) => this . _maybeUpdateViewDimensions ( e ) } >
99
102
{ background }
100
103
{
101
104
React . cloneElement ( scrollElement , {
@@ -110,7 +113,7 @@ class ParallaxScrollView extends Component {
110
113
)
111
114
}
112
115
{ maybeStickyHeader }
113
- </ View >
116
+ </ View >
114
117
) ;
115
118
}
116
119
@@ -142,8 +145,8 @@ class ParallaxScrollView extends Component {
142
145
parallaxHeaderHeight,
143
146
stickyHeaderHeight,
144
147
onChangeHeaderVisibility,
145
- onScroll : prevOnScroll = ( ) => { }
146
- } = this . props ;
148
+ onScroll : prevOnScroll = ( ) => { } ,
149
+ } = this . props ;
147
150
148
151
const p = pivotPoint ( parallaxHeaderHeight , stickyHeaderHeight ) ;
149
152
@@ -177,70 +180,74 @@ class ParallaxScrollView extends Component {
177
180
if ( width !== this . state . viewWidth || height !== this . state . viewHeight ) {
178
181
this . setState ( {
179
182
viewWidth : width ,
180
- viewHeight : height
183
+ viewHeight : height ,
181
184
} ) ;
182
185
}
183
186
}
184
187
185
188
_renderBackground ( { fadeOutBackground, backgroundScrollSpeed, backgroundColor, parallaxHeaderHeight, stickyHeaderHeight, renderBackground } ) {
186
189
const { viewWidth, viewHeight, scrollY } = this . state ;
187
190
const p = pivotPoint ( parallaxHeaderHeight , stickyHeaderHeight ) ;
191
+ const transform = [ {
192
+ translateY : interpolate ( scrollY , {
193
+ inputRange : [ 0 , p ] ,
194
+ outputRange : [ 0 , - ( p / backgroundScrollSpeed ) ] ,
195
+ extrapolateRight : 'extend' ,
196
+ extrapolateLeft : 'clamp' ,
197
+ } ) ,
198
+ } ] ;
199
+ if ( Platform . OS === 'ios' ) {
200
+ transform . push ( {
201
+ scale : interpolate ( scrollY , {
202
+ inputRange : [ - viewHeight , 0 ] ,
203
+ outputRange : [ 5 , 1 ] ,
204
+ extrapolate : 'clamp' ,
205
+ } ) ,
206
+ } ) ;
207
+ }
188
208
return (
189
- < Animated . View
190
- style = { [ styles . backgroundImage , {
191
- backgroundColor : backgroundColor ,
192
- height : parallaxHeaderHeight ,
193
- width : viewWidth ,
194
- opacity : fadeOutBackground
195
- ? interpolate ( scrollY , {
196
- inputRange : [ 0 , p * ( 1 / 2 ) , p * ( 3 / 4 ) , p ] ,
197
- outputRange : [ 1 , 0.3 , 0.1 , 0 ] ,
198
- extrapolate : 'clamp'
199
- } )
200
- : 1 ,
201
- transform : [ {
202
- translateY : interpolate ( scrollY , {
203
- inputRange : [ 0 , p ] ,
204
- outputRange : [ 0 , - ( p / backgroundScrollSpeed ) ] ,
205
- extrapolateRight : 'extend' ,
206
- extrapolateLeft : 'clamp'
207
- } )
208
- } , {
209
- scale : interpolate ( scrollY , {
210
- inputRange : [ - viewHeight , 0 ] ,
211
- outputRange : [ 5 , 1 ] ,
212
- extrapolate : 'clamp'
213
- } )
214
- } ]
215
- } ] } >
216
- < View >
209
+ < Animated . View
210
+ style = { [ styles . backgroundImage , {
211
+ backgroundColor : backgroundColor ,
212
+ height : parallaxHeaderHeight ,
213
+ width : viewWidth ,
214
+ opacity : fadeOutBackground
215
+ ? interpolate ( scrollY , {
216
+ inputRange : [ 0 , p * ( 1 / 2 ) , p * ( 3 / 4 ) , p ] ,
217
+ outputRange : [ 1 , 0.3 , 0.1 , 0 ] ,
218
+ extrapolate : 'clamp' ,
219
+ } )
220
+ : 1 ,
221
+ transform,
222
+ } ] } >
223
+ < View >
217
224
{ renderBackground ( ) }
218
- </ View >
219
- </ Animated . View >
225
+ </ View >
226
+ </ Animated . View >
220
227
) ;
221
228
}
222
229
223
230
_renderForeground ( { fadeOutForeground, parallaxHeaderHeight, stickyHeaderHeight, renderForeground } ) {
224
231
const { scrollY } = this . state ;
225
232
const p = pivotPoint ( parallaxHeaderHeight , stickyHeaderHeight ) ;
226
233
return (
227
- < View style = { styles . parallaxHeaderContainer } >
228
- < Animated . View
229
- style = { [ styles . parallaxHeader , {
230
- height : parallaxHeaderHeight ,
231
- opacity : fadeOutForeground
232
- ? interpolate ( scrollY , {
233
- inputRange : [ 0 , p * ( 1 / 2 ) , p * ( 3 / 4 ) , p ] ,
234
- outputRange : [ 1 , 0.3 , 0.1 , 0 ] ,
235
- extrapolate : 'clamp'
236
- } )
237
- : 1
238
- } ] } >
239
- < View style = { { height : parallaxHeaderHeight } } >
240
- { renderForeground ( ) }
234
+ < View style = { styles . parallaxHeaderContainer } >
235
+ < Animated . View
236
+ style = { [ styles . parallaxHeader , {
237
+ height : parallaxHeaderHeight ,
238
+ opacity : fadeOutForeground
239
+ ? interpolate ( scrollY , {
240
+ inputRange : [ 0 , p * ( 1 / 2 ) , p * ( 3 / 4 ) , p ] ,
241
+ outputRange : [ 1 , 0.3 , 0.1 , 0 ] ,
242
+ extrapolate : 'clamp' ,
243
+ } )
244
+ : 1 ,
245
+ } ] } >
246
+ < View style = { { height : parallaxHeaderHeight } } >
247
+ { renderForeground ( ) }
248
+ </ View >
249
+ </ Animated . View >
241
250
</ View >
242
- </ Animated . View >
243
- </ View >
244
251
) ;
245
252
}
246
253
@@ -252,29 +259,29 @@ class ParallaxScrollView extends Component {
252
259
containerStyles . push ( contentContainerStyle ) ;
253
260
254
261
return (
255
- < View
256
- style = { containerStyles }
257
- onLayout = { e => {
258
- // Adjust the bottom height so we can scroll the parallax header all the way up.
259
- const { nativeEvent : { layout : { height } } } = e ;
260
- const footerHeight = Math . max ( 0 , viewHeight - height - stickyHeaderHeight ) ;
261
- if ( this . _footerHeight !== footerHeight ) {
262
- this . _footerComponent . setNativeProps ( { style : { height : footerHeight } } ) ;
263
- this . _footerHeight = footerHeight ;
264
- }
265
- } } >
262
+ < View
263
+ style = { containerStyles }
264
+ onLayout = { e => {
265
+ // Adjust the bottom height so we can scroll the parallax header all the way up.
266
+ const { nativeEvent : { layout : { height } } } = e ;
267
+ const footerHeight = Math . max ( 0 , viewHeight - height - stickyHeaderHeight ) ;
268
+ if ( this . _footerHeight !== footerHeight ) {
269
+ this . _footerComponent . setNativeProps ( { style : { height : footerHeight } } ) ;
270
+ this . _footerHeight = footerHeight ;
271
+ }
272
+ } } >
266
273
{ children }
267
- </ View >
268
- ) ;
274
+ </ View >
275
+ ) ;
269
276
}
270
277
271
278
_renderFooterSpacer ( { contentBackgroundColor } ) {
272
279
return (
273
- < View ref = { ref => this . _footerComponent = ref } style = { { backgroundColor : contentBackgroundColor } } />
280
+ < View ref = { ref => this . _footerComponent = ref } style = { { backgroundColor : contentBackgroundColor } } />
274
281
) ;
275
282
}
276
283
277
- _maybeRenderStickyHeader ( { parallaxHeaderHeight, stickyHeaderHeight, backgroundColor, renderFixedHeader, renderStickyHeader } ) {
284
+ _maybeRenderStickyHeader ( { parallaxHeaderHeight, stickyHeaderHeight, backgroundColor, renderFixedHeader, renderStickyHeader, scrollingStickyHeader } ) {
278
285
const { viewWidth, scrollY } = this . state ;
279
286
if ( renderStickyHeader || renderFixedHeader ) {
280
287
const p = pivotPoint ( parallaxHeaderHeight , stickyHeaderHeight ) ;
@@ -283,39 +290,42 @@ class ParallaxScrollView extends Component {
283
290
outputRange : [ 0 , stickyHeaderHeight ] ,
284
291
extrapolate : 'clamp' ,
285
292
} ) ;
293
+ const stickyHeader = scrollingStickyHeader ? (
294
+ < Animated . View
295
+ style = { {
296
+ transform : [ {
297
+ translateY : interpolate ( scrollY , {
298
+ inputRange : [ 0 , p ] ,
299
+ outputRange : [ stickyHeaderHeight , 0 ] ,
300
+ extrapolate : 'clamp' ,
301
+ } ) ,
302
+ } ] ,
303
+ } } >
304
+ { this . renderStickyHeader ( ) }
305
+ </ Animated . View >
306
+ ) : renderStickyHeader ( ) ;
286
307
return (
287
308
< View style = { [ styles . stickyHeader , { width : viewWidth } ] } >
288
309
{
289
310
renderStickyHeader
290
311
? (
291
- < Animated . View
292
- style = { {
293
- backgroundColor : backgroundColor ,
294
- height : height ,
295
- opacity : interpolate ( scrollY , {
296
- inputRange : [ 0 , p ] ,
297
- outputRange : [ 0 , 1 ] ,
298
- extrapolate : 'clamp'
299
- } )
300
- } } >
301
- < Animated . View
302
- style = { {
303
- transform : [ {
304
- translateY : interpolate ( scrollY , {
305
- inputRange : [ 0 , p ] ,
306
- outputRange : [ stickyHeaderHeight , 0 ] ,
307
- extrapolate : 'clamp'
308
- } )
309
- } ]
312
+ < Animated . View
313
+ style = { {
314
+ backgroundColor : backgroundColor ,
315
+ height : height ,
316
+ opacity : interpolate ( scrollY , {
317
+ inputRange : [ 0 , p ] ,
318
+ outputRange : [ 0 , 1 ] ,
319
+ extrapolate : 'clamp' ,
320
+ } ) ,
310
321
} } >
311
- { renderStickyHeader ( ) }
312
- </ Animated . View >
313
- </ Animated . View >
322
+ { stickyHeader }
323
+ </ Animated . View >
314
324
)
315
325
: null
316
326
}
317
327
{ renderFixedHeader && renderFixedHeader ( ) }
318
- </ View >
328
+ </ View >
319
329
) ;
320
330
} else {
321
331
return null ;
@@ -336,7 +346,8 @@ ParallaxScrollView.defaultProps = {
336
346
renderParallaxHeader : renderEmpty , // Deprecated (will be removed in 0.18.0)
337
347
renderForeground : null ,
338
348
stickyHeaderHeight : 0 ,
339
- contentContainerStyle : null
349
+ contentContainerStyle : null ,
350
+ scrollingStickyheader : true ,
340
351
} ;
341
352
342
353
module . exports = ParallaxScrollView ;
0 commit comments