@@ -2,6 +2,7 @@ import React, { Component } from 'react';
22import {
33 Animated ,
44 Dimensions ,
5+ Platform ,
56 ScrollView ,
67 View ,
78 ViewPropTypes ,
@@ -45,6 +46,7 @@ const IPropTypes = {
4546 renderStickyHeader : func ,
4647 stickyHeaderHeight : number ,
4748 contentContainerStyle : ViewPropTypes . style ,
49+ scrollingStickyHeader : bool ,
4850} ;
4951
5052class ParallaxScrollView extends Component {
@@ -59,7 +61,7 @@ class ParallaxScrollView extends Component {
5961 this . state = {
6062 scrollY : new Animated . Value ( 0 ) ,
6163 viewHeight : window . height ,
62- viewWidth : window . width
64+ viewWidth : window . width ,
6365 } ;
6466 this . _footerComponent = { setNativeProps ( ) { } } ; // Initial stub
6567 this . _footerHeight = 0 ;
@@ -83,19 +85,20 @@ class ParallaxScrollView extends Component {
8385 stickyHeaderHeight,
8486 style,
8587 contentContainerStyle,
88+ scrollingStickyHeader,
8689 ...scrollViewProps
8790 } = this . props ;
8891
8992 const background = this . _renderBackground ( { fadeOutBackground, backgroundScrollSpeed, backgroundColor, parallaxHeaderHeight, stickyHeaderHeight, renderBackground } ) ;
9093 const foreground = this . _renderForeground ( { fadeOutForeground, parallaxHeaderHeight, stickyHeaderHeight, renderForeground : renderForeground || renderParallaxHeader } ) ;
9194 const bodyComponent = this . _wrapChildren ( children , { contentBackgroundColor, stickyHeaderHeight, contentContainerStyle } ) ;
9295 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 } ) ;
9497 const scrollElement = renderScrollComponent ( scrollViewProps ) ;
9598
9699 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 ) } >
99102 { background }
100103 {
101104 React . cloneElement ( scrollElement , {
@@ -110,7 +113,7 @@ class ParallaxScrollView extends Component {
110113 )
111114 }
112115 { maybeStickyHeader }
113- </ View >
116+ </ View >
114117 ) ;
115118 }
116119
@@ -142,8 +145,8 @@ class ParallaxScrollView extends Component {
142145 parallaxHeaderHeight,
143146 stickyHeaderHeight,
144147 onChangeHeaderVisibility,
145- onScroll : prevOnScroll = ( ) => { }
146- } = this . props ;
148+ onScroll : prevOnScroll = ( ) => { } ,
149+ } = this . props ;
147150
148151 const p = pivotPoint ( parallaxHeaderHeight , stickyHeaderHeight ) ;
149152
@@ -177,70 +180,74 @@ class ParallaxScrollView extends Component {
177180 if ( width !== this . state . viewWidth || height !== this . state . viewHeight ) {
178181 this . setState ( {
179182 viewWidth : width ,
180- viewHeight : height
183+ viewHeight : height ,
181184 } ) ;
182185 }
183186 }
184187
185188 _renderBackground ( { fadeOutBackground, backgroundScrollSpeed, backgroundColor, parallaxHeaderHeight, stickyHeaderHeight, renderBackground } ) {
186189 const { viewWidth, viewHeight, scrollY } = this . state ;
187190 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+ }
188208 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 >
217224 { renderBackground ( ) }
218- </ View >
219- </ Animated . View >
225+ </ View >
226+ </ Animated . View >
220227 ) ;
221228 }
222229
223230 _renderForeground ( { fadeOutForeground, parallaxHeaderHeight, stickyHeaderHeight, renderForeground } ) {
224231 const { scrollY } = this . state ;
225232 const p = pivotPoint ( parallaxHeaderHeight , stickyHeaderHeight ) ;
226233 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 >
241250 </ View >
242- </ Animated . View >
243- </ View >
244251 ) ;
245252 }
246253
@@ -252,29 +259,29 @@ class ParallaxScrollView extends Component {
252259 containerStyles . push ( contentContainerStyle ) ;
253260
254261 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+ } } >
266273 { children }
267- </ View >
268- ) ;
274+ </ View >
275+ ) ;
269276 }
270277
271278 _renderFooterSpacer ( { contentBackgroundColor } ) {
272279 return (
273- < View ref = { ref => this . _footerComponent = ref } style = { { backgroundColor : contentBackgroundColor } } />
280+ < View ref = { ref => this . _footerComponent = ref } style = { { backgroundColor : contentBackgroundColor } } />
274281 ) ;
275282 }
276283
277- _maybeRenderStickyHeader ( { parallaxHeaderHeight, stickyHeaderHeight, backgroundColor, renderFixedHeader, renderStickyHeader } ) {
284+ _maybeRenderStickyHeader ( { parallaxHeaderHeight, stickyHeaderHeight, backgroundColor, renderFixedHeader, renderStickyHeader, scrollingStickyHeader } ) {
278285 const { viewWidth, scrollY } = this . state ;
279286 if ( renderStickyHeader || renderFixedHeader ) {
280287 const p = pivotPoint ( parallaxHeaderHeight , stickyHeaderHeight ) ;
@@ -283,39 +290,42 @@ class ParallaxScrollView extends Component {
283290 outputRange : [ 0 , stickyHeaderHeight ] ,
284291 extrapolate : 'clamp' ,
285292 } ) ;
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 ( ) ;
286307 return (
287308 < View style = { [ styles . stickyHeader , { width : viewWidth } ] } >
288309 {
289310 renderStickyHeader
290311 ? (
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+ } ) ,
310321 } } >
311- { renderStickyHeader ( ) }
312- </ Animated . View >
313- </ Animated . View >
322+ { stickyHeader }
323+ </ Animated . View >
314324 )
315325 : null
316326 }
317327 { renderFixedHeader && renderFixedHeader ( ) }
318- </ View >
328+ </ View >
319329 ) ;
320330 } else {
321331 return null ;
@@ -336,7 +346,8 @@ ParallaxScrollView.defaultProps = {
336346 renderParallaxHeader : renderEmpty , // Deprecated (will be removed in 0.18.0)
337347 renderForeground : null ,
338348 stickyHeaderHeight : 0 ,
339- contentContainerStyle : null
349+ contentContainerStyle : null ,
350+ scrollingStickyheader : true ,
340351} ;
341352
342353module . exports = ParallaxScrollView ;
0 commit comments