From cbd227c6dfd17a58d0751b8e8a42119f53755390 Mon Sep 17 00:00:00 2001 From: Brent Vatne Date: Wed, 31 Oct 2018 13:22:03 -0700 Subject: [PATCH] Default to hide hidden header backgrounds --- packages/stack/example/App.js | 23 +++- .../stack/example/src/HeaderBackgrounds.js | 118 ++++++++++++++++++ .../views/Header/HeaderStyleInterpolator.js | 26 +++- 3 files changed, 161 insertions(+), 6 deletions(-) create mode 100644 packages/stack/example/src/HeaderBackgrounds.js diff --git a/packages/stack/example/App.js b/packages/stack/example/App.js index d776cf4b..47fe32b0 100644 --- a/packages/stack/example/App.js +++ b/packages/stack/example/App.js @@ -16,6 +16,11 @@ import LifecycleInteraction from './src/LifecycleInteraction'; import GestureInteraction from './src/GestureInteraction'; import SwitchWithStacks from './src/SwitchWithStacks'; import StackWithDrawer from './src/StackWithDrawer'; +import { + HeaderBackgroundDefault, + HeaderBackgroundTranslate, + HeaderBackgroundFade, +} from './src/HeaderBackgrounds'; // Comment the following two lines to stop using react-native-screens import { useScreens } from 'react-native-screens'; @@ -54,6 +59,21 @@ const data = [ title: 'Stack with drawer inside', routeName: 'StackWithDrawer', }, + { + component: HeaderBackgroundDefault, + title: 'Header background (default transition)', + routeName: 'HeaderBackgroundDefault', + }, + { + component: HeaderBackgroundFade, + title: 'Header background (fade transition)', + routeName: 'HeaderBackgroundFade', + }, + { + component: HeaderBackgroundTranslate, + title: 'Header background (translate transition)', + routeName: 'HeaderBackgroundTranslate', + }, ]; // Cache images @@ -103,9 +123,6 @@ const Root = createStackNavigator( { mode: 'modal', headerMode: 'none', - defaultNavigationOptions: { - gesturesEnabled: false, - }, } ); diff --git a/packages/stack/example/src/HeaderBackgrounds.js b/packages/stack/example/src/HeaderBackgrounds.js new file mode 100644 index 00000000..0d4ae22b --- /dev/null +++ b/packages/stack/example/src/HeaderBackgrounds.js @@ -0,0 +1,118 @@ +import React, { Component } from 'react'; +import { StyleSheet, View, Text } from 'react-native'; +import { + createStackNavigator, + HeaderStyleInterpolator, +} from 'react-navigation-stack'; + +function createHeaderBackgroundExample(options = {}) { + return createStackNavigator( + { + Login: { + screen: ({ navigation }) => ( + + navigation.navigate('Games')} + > + Login Screen + + + ), + navigationOptions: { + headerTitle: 'Login Screen', + headerTintColor: '#fff', + headerBackground: ( + + ), + }, + }, + Games: { + screen: ({ navigation }) => ( + + navigation.navigate('Main')} + > + Games Screen + + + ), + navigationOptions: { + headerTitle: 'Games Screen', + headerTintColor: '#fff', + headerBackground: ( + + ), + }, + }, + Main: { + screen: ({ navigation }) => ( + + navigation.navigate('My')}> + Main Screen + + + ), + navigationOptions: { + headerTitle: 'Main Screen', + }, + }, + My: { + screen: ({ navigation }) => ( + + navigation.navigate('News')} + > + My Screen + + + ), + navigationOptions: { + headerTitle: 'My Screen', + }, + }, + News: { + screen: ({ navigation }) => ( + + {}}> + News Screen + + + ), + navigationOptions: { + headerTitle: 'News Screen', + }, + }, + }, + { + initialRouteName: 'Login', + ...options, + } + ); +} +export const HeaderBackgroundDefault = createHeaderBackgroundExample(); +export const HeaderBackgroundTranslate = createHeaderBackgroundExample({ + transitionConfig: () => ({ + headerBackgroundInterpolator: + HeaderStyleInterpolator.forBackgroundWithTranslation, + }), +}); +export const HeaderBackgroundFade = createHeaderBackgroundExample({ + transitionConfig: () => ({ + headerBackgroundInterpolator: HeaderStyleInterpolator.forBackgroundWithFade, + }), +}); + +const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: '#F5FCFF', + justifyContent: 'center', + alignItems: 'center', + }, + tips: { + fontSize: 20, + }, +}); diff --git a/packages/stack/src/views/Header/HeaderStyleInterpolator.js b/packages/stack/src/views/Header/HeaderStyleInterpolator.js index 60a0b5e9..cb80380a 100644 --- a/packages/stack/src/views/Header/HeaderStyleInterpolator.js +++ b/packages/stack/src/views/Header/HeaderStyleInterpolator.js @@ -1,6 +1,8 @@ import { Dimensions, I18nManager } from 'react-native'; import getSceneIndicesForInterpolationInputRange from '../../utils/getSceneIndicesForInterpolationInputRange'; +const EPS = 1e-5; + function hasHeader(scene) { if (!scene) { return true; @@ -28,6 +30,7 @@ const crossFadeInterpolation = (scenes, first, index, last) => ({ hasHeader(scenes[last]) ? 0 : 1, 0, ], + extrapolate: 'clamp', }); /** @@ -87,6 +90,7 @@ function forLayout(props) { rtlMult * (hasHeader(scenes[index]) ? 0 : isBack ? width : -width), rtlMult * (hasHeader(scenes[last]) ? 0 : -width), ], + extrapolate: 'clamp', }); return { @@ -181,6 +185,7 @@ function forLeftButton(props) { opacity: position.interpolate({ inputRange, outputRange, + extrapolate: 'clamp', }), }; } @@ -230,6 +235,7 @@ function forLeftLabel(props) { hasHeader(scenes[last]) ? 0 : 1, 0, ], + extrapolate: 'clamp', }), transform: [ { @@ -250,6 +256,7 @@ function forLeftLabel(props) { hasHeader(scenes[last]) ? -offset * 1.5 : 0, -offset * 1.5, ], + extrapolate: 'clamp', }), }, ], @@ -298,6 +305,7 @@ function forCenterFromLeft(props) { hasHeader(scenes[last]) ? 0 : 1, 0, ], + extrapolate: 'clamp', }), transform: [ { @@ -318,6 +326,7 @@ function forCenterFromLeft(props) { hasHeader(scenes[last]) ? -offset : 0, -offset, ], + extrapolate: 'clamp', }), }, ], @@ -332,13 +341,19 @@ function forBackgroundWithFade(props) { return { opacity: position.interpolate({ inputRange: [sceneRange.first, scene.index, sceneRange.last], - outputRange: [0, 1, 1], + outputRange: [0, 1, 0], + extrapolate: 'clamp', }), }; } -// Default to fade transition -const forBackground = forBackgroundWithFade; +const VISIBLE = { opacity: 1 }; +const HIDDEN = { opacity: 0 }; + +// Toggle visibility of header without fading +function forBackgroundWithInactiveHidden({ navigation, scene }) { + return navigation.state.index === scene.index ? VISIBLE : HIDDEN; +} // Translate the background with the card const BACKGROUND_OFFSET = Dimensions.get('window').width; @@ -356,12 +371,16 @@ function forBackgroundWithTranslation(props) { translateX: position.interpolate({ inputRange: [first, index, last], outputRange: I18nManager.isRTL ? outputRange.reverse() : outputRange, + extrapolate: 'clamp', }), }, ], }; } +// Default to fade transition +const forBackground = forBackgroundWithInactiveHidden; + export default { forLayout, forLeft, @@ -371,6 +390,7 @@ export default { forCenter, forRight, forBackground, + forBackgroundWithInactiveHidden, forBackgroundWithFade, forBackgroundWithTranslation, };