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,
titleInterpolator: HeaderStyleInterpolator.forCenter,
rightInterpolator: HeaderStyleInterpolator.forRight,
backgroundInterpolator: HeaderStyleInterpolator.forBackground,
};
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(
props,
name,
@ -492,6 +516,7 @@ class Header extends React.PureComponent {
render() {
let appBar;
let background;
const { mode, scene, isLandscape } = this.props;
if (mode === 'float') {
@ -505,12 +530,16 @@ class Header extends React.PureComponent {
scene,
}));
appBar = scenesProps.map(this._renderHeader, this);
background = scenesProps.map(this._renderBackground, this);
} else {
appBar = this._renderHeader({
const headerProps = {
position: new Animated.Value(this.props.scene.index),
progress: new Animated.Value(0),
scene: this.props.scene,
});
};
appBar = this._renderHeader(headerProps);
background = this._renderBackground(headerProps);
}
const { options } = scene.descriptor;
@ -590,9 +619,7 @@ class Header extends React.PureComponent {
]}
>
<SafeAreaView forceInset={forceInset} style={containerStyles}>
<View style={StyleSheet.absoluteFill}>
{options.headerBackground}
</View>
{background}
<View style={styles.flexOne}>{appBar}</View>
</SafeAreaView>
</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 {
forLayout,
forLeft,
@ -333,4 +354,5 @@ export default {
forCenterFromLeft,
forCenter,
forRight,
forBackground,
};