Merge pull request #3 from erickreutz/eric-interpolated-background

Animate headerBackground between scene transitions
This commit is contained in:
Brent Vatne 2018-08-21 12:55:48 -07:00 committed by GitHub
commit 6a76bf6703
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 54 additions and 5 deletions

View File

@ -80,6 +80,7 @@ class Header extends React.PureComponent {
titleFromLeftInterpolator: HeaderStyleInterpolator.forCenterFromLeft, titleFromLeftInterpolator: HeaderStyleInterpolator.forCenterFromLeft,
titleInterpolator: HeaderStyleInterpolator.forCenter, titleInterpolator: HeaderStyleInterpolator.forCenter,
rightInterpolator: HeaderStyleInterpolator.forRight, rightInterpolator: HeaderStyleInterpolator.forRight,
backgroundInterpolator: HeaderStyleInterpolator.forBackground,
}; };
static get HEIGHT() { static get HEIGHT() {
@ -338,6 +339,29 @@ class Header extends React.PureComponent {
); );
} }
_renderBackground(props) {
const {
index,
key,
descriptor: { options },
} = props.scene;
const offset = this.props.navigation.state.index - index;
if (Math.abs(offset) > 2) {
// Scene is far away from the active scene. Hides it to avoid unnecessary
// rendering.
return null;
}
return this._renderSubView(
{ ...props, style: StyleSheet.absoluteFill },
'background',
() => options.headerBackground,
this.props.backgroundInterpolator
);
}
_renderModularSubView( _renderModularSubView(
props, props,
name, name,
@ -492,6 +516,7 @@ class Header extends React.PureComponent {
render() { render() {
let appBar; let appBar;
let background;
const { mode, scene, isLandscape } = this.props; const { mode, scene, isLandscape } = this.props;
if (mode === 'float') { if (mode === 'float') {
@ -505,12 +530,16 @@ class Header extends React.PureComponent {
scene, scene,
})); }));
appBar = scenesProps.map(this._renderHeader, this); appBar = scenesProps.map(this._renderHeader, this);
background = scenesProps.map(this._renderBackground, this);
} else { } else {
appBar = this._renderHeader({ const headerProps = {
position: new Animated.Value(this.props.scene.index), position: new Animated.Value(this.props.scene.index),
progress: new Animated.Value(0), progress: new Animated.Value(0),
scene: this.props.scene, scene: this.props.scene,
}); };
appBar = this._renderHeader(headerProps);
background = this._renderBackground(headerProps);
} }
const { options } = scene.descriptor; const { options } = scene.descriptor;
@ -590,9 +619,7 @@ class Header extends React.PureComponent {
]} ]}
> >
<SafeAreaView forceInset={forceInset} style={containerStyles}> <SafeAreaView forceInset={forceInset} style={containerStyles}>
<View style={StyleSheet.absoluteFill}> {background}
{options.headerBackground}
</View>
<View style={styles.flexOne}>{appBar}</View> <View style={styles.flexOne}>{appBar}</View>
</SafeAreaView> </SafeAreaView>
</Animated.View> </Animated.View>

View File

@ -325,6 +325,27 @@ function forCenterFromLeft(props) {
}; };
} }
const BACKGROUND_OFFSET = Dimensions.get('window').width;
function forBackground(props) {
const { position, scene, scenes } = props;
const interpolate = getSceneIndicesForInterpolationInputRange(props);
if (!interpolate) return { opacity: 0 };
const { first, last } = interpolate;
const index = scene.index;
const offset = BACKGROUND_OFFSET;
const outputRange = [offset, 0, -offset];
return {
transform: [
{
translateX: position.interpolate({
inputRange: [first, index, last],
outputRange: I18nManager.isRTL ? outputRange.reverse() : outputRange,
}),
},
],
};
}
export default { export default {
forLayout, forLayout,
forLeft, forLeft,
@ -333,4 +354,5 @@ export default {
forCenterFromLeft, forCenterFromLeft,
forCenter, forCenter,
forRight, forRight,
forBackground,
}; };