diff --git a/src/index.js b/src/index.js index 19e25a5..02c4ae1 100644 --- a/src/index.js +++ b/src/index.js @@ -1,5 +1,5 @@ import React, { Component } from 'react' -import { Animated, Dimensions, ScrollView, View, ViewPropTypes } from 'react-native' +import { Animated, Dimensions, View, ViewPropTypes } from 'react-native' const styles = require('./styles') @@ -13,6 +13,8 @@ const pivotPoint = (a, b) => a - b const renderEmpty = () => +const noRender = () => + // Override `toJSON` of interpolated value because of // an error when serializing style on view inside inspector. // See: https://github.com/jaysoo/react-native-parallax-scroll-view/issues/23 @@ -32,6 +34,7 @@ const IPropTypes = { onChangeHeaderVisibility: func, parallaxHeaderHeight: number.isRequired, renderBackground: func, + renderContentBackground: func, renderFixedHeader: func, renderForeground: func, renderScrollComponent: func, @@ -60,7 +63,7 @@ class ParallaxScrollView extends Component { viewWidth: window.width } this.scrollY = new Animated.Value(0) - this._footerComponent = { setNativeProps() {} } // Initial stub + this._footerComponent = { setNativeProps() { } } // Initial stub this._footerHeight = 0 } @@ -79,6 +82,7 @@ class ParallaxScrollView extends Component { fadeOutBackground, parallaxHeaderHeight, renderBackground, + renderContentBackground, renderFixedHeader, renderForeground, renderParallaxHeader, @@ -109,6 +113,7 @@ class ParallaxScrollView extends Component { const bodyComponent = this._wrapChildren(children, { contentBackgroundColor, stickyHeaderHeight, + renderContentBackground, contentContainerStyle }) const footerSpacer = this._renderFooterSpacer({ contentBackgroundColor }) @@ -136,9 +141,19 @@ class ParallaxScrollView extends Component { onScroll: Animated.event( [{ nativeEvent: { contentOffset: { y: this.scrollY } } }], { useNativeDriver: true, listener: this._onScroll.bind(this) } - ) + ), + onContentSizeChange: (contentWidth, contentHeight) => { + if (contentHeight != this._mainHeight) { + const footerHeight = Math.max(0, this.state.viewHeight - this._mainHeight - stickyHeaderHeight);// this._mainHeight set by onLayout + if (this._footerHeight !== footerHeight) { + this._footerComponent.setNativeProps({ style: { height: footerHeight } }); + this._footerHeight = footerHeight; + } + } + } // onScroll: this._onScroll.bind(this) }, + foreground, bodyComponent, footerSpacer @@ -176,7 +191,7 @@ class ParallaxScrollView extends Component { parallaxHeaderHeight, stickyHeaderHeight, onChangeHeaderVisibility, - onScroll: prevOnScroll = e => {} + onScroll: prevOnScroll = () => { } } = this.props this.props.scrollEvent && this.props.scrollEvent(e) const p = pivotPoint(parallaxHeaderHeight, stickyHeaderHeight) @@ -206,13 +221,18 @@ class ParallaxScrollView extends Component { } _maybeUpdateViewDimensions(e) { - const { nativeEvent: { layout: { width, height } } } = e - + const { stickyHeaderHeight } = this.props; + const { nativeEvent: { layout: { width, height } } } = e; if (width !== this.state.viewWidth || height !== this.state.viewHeight) { + const footerHeight = Math.max(0, height - this.mainHeight - stickyHeaderHeight);// this.mainHeight set by onLayout + if (this._footerHeight !== footerHeight) { + this._footerComponent.setNativeProps({ style: { height: footerHeight } }); + this._footerHeight = footerHeight; + } this.setState({ viewWidth: width, viewHeight: height - }) + }); } } @@ -238,10 +258,10 @@ class ParallaxScrollView extends Component { width: viewWidth, opacity: fadeOutBackground ? interpolate(scrollY, { - inputRange: [0, p * (1 / 2), p * (3 / 4), p], - outputRange: [1, 0.3, 0.1, 0], - extrapolate: 'clamp' - }) + inputRange: [0, p * (1 / 2), p * (3 / 4), p], + outputRange: [1, 0.3, 0.1, 0], + extrapolate: 'clamp' + }) : 1, transform: [ { @@ -255,7 +275,7 @@ class ParallaxScrollView extends Component { { scale: interpolate(scrollY, { inputRange: [-viewHeight, 0], - outputRange: [outputScaleValue, 1], + outputRange: [outputScaleValue * 1.5, 1], extrapolate: 'clamp' }) } @@ -287,10 +307,10 @@ class ParallaxScrollView extends Component { height: parallaxHeaderHeight, opacity: fadeOutForeground ? interpolate(scrollY, { - inputRange: [0, p * (1 / 2), p * (3 / 4), p], - outputRange: [1, 0.3, 0.1, 0], - extrapolate: 'clamp' - }) + inputRange: [0, p * (1 / 2), p * (3 / 4), p], + outputRange: [1, 0.3, 0.1, 0], + extrapolate: 'clamp' + }) : 1 } ]} @@ -305,16 +325,24 @@ class ParallaxScrollView extends Component { _wrapChildren( children, - { contentBackgroundColor, stickyHeaderHeight, contentContainerStyle } + { contentBackgroundColor, stickyHeaderHeight, contentContainerStyle, renderContentBackground } ) { const { viewHeight } = this.state const containerStyles = [{ backgroundColor: contentBackgroundColor }] if (contentContainerStyle) containerStyles.push(contentContainerStyle) + this.containerHeight = this.state.viewHeight; + + React.Children.forEach(children, (item) => { + if (item && Object.keys(item).length != 0) { + this.containerHeight = 0; + } + }); + return ( { // Adjust the bottom height so we can scroll the parallax header all the way up. const { nativeEvent: { layout: { height } } } = e @@ -330,6 +358,7 @@ class ParallaxScrollView extends Component { } }} > + {renderContentBackground()} {children} ) @@ -338,7 +367,11 @@ class ParallaxScrollView extends Component { _renderFooterSpacer({ contentBackgroundColor }) { return ( (this._footerComponent = ref)} + ref={ref => { + if (ref) { + this._footerComponent = ref; + } + }} style={{ backgroundColor: contentBackgroundColor }} /> ) @@ -367,32 +400,32 @@ class ParallaxScrollView extends Component { > {renderStickyHeader ? + - - {renderStickyHeader()} - + {renderStickyHeader()} + : null} {renderFixedHeader && renderFixedHeader()} @@ -410,9 +443,10 @@ ParallaxScrollView.defaultProps = { backgroundColor: '#000', contentBackgroundColor: '#fff', fadeOutForeground: true, - onChangeHeaderVisibility: () => {}, + onChangeHeaderVisibility: () => { }, renderScrollComponent: props => , renderBackground: renderEmpty, + renderContentBackground: noRender, renderParallaxHeader: renderEmpty, // Deprecated (will be removed in 0.18.0) renderForeground: null, stickyHeaderHeight: 0,