fix: make the header appear static when sibling of headerless screen

This commit is contained in:
satyajit.happy
2019-06-14 18:56:22 +02:00
parent 72426c2679
commit 2f6576636a
6 changed files with 102 additions and 76 deletions

View File

@@ -102,6 +102,28 @@ export function forFade({
};
}
export function forStatic({
progress: { current, next },
layouts: { screen },
}: HeaderInterpolationProps): HeaderInterpolatedStyle {
const progress = add(current, next ? next : 0);
const translateX = interpolate(progress, {
inputRange: [0, 1, 2],
outputRange: I18nManager.isRTL
? [-screen.width, 0, screen.width]
: [screen.width, 0, -screen.width],
});
const transform = [{ translateX }];
return {
leftButtonStyle: { transform },
rightButtonStyle: { transform },
titleStyle: { transform },
backgroundStyle: { transform },
};
}
export function forNoAnimation(): HeaderInterpolatedStyle {
return {};
}

View File

@@ -36,18 +36,13 @@ Array [
onTransitionStart={[Function]}
pointerEvents="box-none"
style={
Array [
Object {
"bottom": 0,
"left": 0,
"position": "absolute",
"right": 0,
"top": 0,
},
Object {
"marginTop": 64,
},
]
Object {
"bottom": 0,
"left": 0,
"position": "absolute",
"right": 0,
"top": 0,
}
}
transitionSpec={
Object {
@@ -103,6 +98,9 @@ Array [
"overflow": "hidden",
},
undefined,
Object {
"marginTop": 64,
},
]
}
>
@@ -168,11 +166,8 @@ Array [
style={
Array [
Object {
"bottom": 0,
"left": 0,
"position": "absolute",
"right": 0,
"top": 0,
"flex": 1,
"overflow": "hidden",
},
Object {
"backgroundColor": "#eee",
@@ -214,18 +209,13 @@ Array [
onTransitionStart={[Function]}
pointerEvents="box-none"
style={
Array [
Object {
"bottom": 0,
"left": 0,
"position": "absolute",
"right": 0,
"top": 0,
},
Object {
"marginTop": 64,
},
]
Object {
"bottom": 0,
"left": 0,
"position": "absolute",
"right": 0,
"top": 0,
}
}
transitionSpec={
Object {
@@ -281,6 +271,9 @@ Array [
"overflow": "hidden",
},
undefined,
Object {
"marginTop": 64,
},
]
}
>
@@ -346,11 +339,8 @@ Array [
style={
Array [
Object {
"bottom": 0,
"left": 0,
"position": "absolute",
"right": 0,
"top": 0,
"flex": 1,
"overflow": "hidden",
},
Object {
"backgroundColor": "#eee",

View File

@@ -36,18 +36,13 @@ Array [
onTransitionStart={[Function]}
pointerEvents="box-none"
style={
Array [
Object {
"bottom": 0,
"left": 0,
"position": "absolute",
"right": 0,
"top": 0,
},
Object {
"marginTop": 64,
},
]
Object {
"bottom": 0,
"left": 0,
"position": "absolute",
"right": 0,
"top": 0,
}
}
transitionSpec={
Object {
@@ -103,6 +98,9 @@ Array [
"overflow": "hidden",
},
undefined,
Object {
"marginTop": 64,
},
]
}
>
@@ -168,11 +166,8 @@ Array [
style={
Array [
Object {
"bottom": 0,
"left": 0,
"position": "absolute",
"right": 0,
"top": 0,
"flex": 1,
"overflow": "hidden",
},
Object {
"backgroundColor": "#eee",
@@ -371,18 +366,13 @@ Array [
onTransitionStart={[Function]}
pointerEvents="box-none"
style={
Array [
Object {
"bottom": 0,
"left": 0,
"position": "absolute",
"right": 0,
"top": 0,
},
Object {
"marginTop": 64,
},
]
Object {
"bottom": 0,
"left": 0,
"position": "absolute",
"right": 0,
"top": 0,
}
}
transitionSpec={
Object {
@@ -438,6 +428,9 @@ Array [
"overflow": "hidden",
},
undefined,
Object {
"marginTop": 64,
},
]
}
>
@@ -503,11 +496,8 @@ Array [
style={
Array [
Object {
"bottom": 0,
"left": 0,
"position": "absolute",
"right": 0,
"top": 0,
"flex": 1,
"overflow": "hidden",
},
Object {
"backgroundColor": "#eee",

View File

@@ -15,6 +15,7 @@ import {
HeaderStyleInterpolator,
} from '../../types';
import Header from './Header';
import { forStatic } from '../../TransitionConfigs/HeaderStyleInterpolators';
export type Props = {
mode: 'float' | 'screen';
@@ -65,13 +66,27 @@ export default function HeaderContainer({
}
}
// If the screen is next to a headerless screen, we need to make the header appear static
// This makes the header look like it's moving with the screen
const previousScene = self[i - 1];
const nextScene = self[i + 1];
const isHeaderStatic =
mode === 'float'
? (previousScene &&
previousScene.descriptor.options.header === null &&
// We still need to animate when coming back from next scene
// A hacky way to check this is if the next scene exists
!nextScene) ||
(nextScene && nextScene.descriptor.options.header === null)
: false;
const props = {
mode,
layout,
scene,
previous,
navigation: scene.descriptor.navigation,
styleInterpolator,
styleInterpolator: isHeaderStatic ? forStatic : styleInterpolator,
};
return (

View File

@@ -1,5 +1,12 @@
import * as React from 'react';
import { View, I18nManager, StyleSheet, ViewProps } from 'react-native';
import {
View,
I18nManager,
StyleSheet,
ViewProps,
StyleProp,
ViewStyle,
} from 'react-native';
import Animated from 'react-native-reanimated';
import {
PanGestureHandler,
@@ -37,6 +44,7 @@ type Props = ViewProps & {
close: TransitionSpec;
};
styleInterpolator: CardStyleInterpolator;
containerStyle?: StyleProp<ViewStyle>;
};
type Binary = 0 | 1;
@@ -463,6 +471,7 @@ export default class Card extends React.Component<Props> {
gesturesEnabled,
children,
styleInterpolator,
containerStyle: customContainerStyle,
...rest
} = this.props;
@@ -489,7 +498,7 @@ export default class Card extends React.Component<Props> {
/>
) : null}
<Animated.View
style={[styles.container, containerStyle]}
style={[styles.container, containerStyle, customContainerStyle]}
pointerEvents="box-none"
>
<PanGestureHandler
@@ -510,7 +519,7 @@ export default class Card extends React.Component<Props> {
active={active}
progress={this.props.current}
style={[
StyleSheet.absoluteFill,
styles.container,
transparent ? styles.transparent : styles.opaque,
]}
>

View File

@@ -128,12 +128,12 @@ export default class StackItem extends React.PureComponent<Props> {
accessibilityElementsHidden={!focused}
importantForAccessibility={focused ? 'auto' : 'no-hide-descendants'}
pointerEvents="box-none"
style={[
StyleSheet.absoluteFill,
containerStyle={
headerMode === 'float' && !hasCustomHeader
? { marginTop: floaingHeaderHeight }
: null,
]}
: null
}
style={StyleSheet.absoluteFill}
>
{headerMode === 'screen'
? renderHeader({