diff --git a/packages/stack/src/index.tsx b/packages/stack/src/index.tsx index 11c38fdb..85121f2b 100644 --- a/packages/stack/src/index.tsx +++ b/packages/stack/src/index.tsx @@ -37,11 +37,11 @@ export { * Utilities */ export { default as CardAnimationContext } from './utils/CardAnimationContext'; -export { default as FloatingHeaderHeightContext } from './utils/FloatingHeaderHeightContext'; +export { default as HeaderHeightContext } from './utils/HeaderHeightContext'; export { default as GestureHandlerRefContext } from './utils/GestureHandlerRefContext'; export { default as useCardAnimation } from './utils/useCardAnimation'; -export { default as useFloatingHeaderHeight } from './utils/useFloatingHeaderHeight'; +export { default as useHeaderHeight } from './utils/useHeaderHeight'; export { default as useGestureHandlerRef } from './utils/useGestureHandlerRef'; /** diff --git a/packages/stack/src/utils/FloatingHeaderHeightContext.tsx b/packages/stack/src/utils/FloatingHeaderHeightContext.tsx deleted file mode 100644 index f31f9dac..00000000 --- a/packages/stack/src/utils/FloatingHeaderHeightContext.tsx +++ /dev/null @@ -1,3 +0,0 @@ -import * as React from 'react'; - -export default React.createContext(0); diff --git a/packages/stack/src/utils/HeaderHeightContext.tsx b/packages/stack/src/utils/HeaderHeightContext.tsx new file mode 100644 index 00000000..e61d0446 --- /dev/null +++ b/packages/stack/src/utils/HeaderHeightContext.tsx @@ -0,0 +1,3 @@ +import * as React from 'react'; + +export default React.createContext(undefined); diff --git a/packages/stack/src/utils/useFloatingHeaderHeight.tsx b/packages/stack/src/utils/useFloatingHeaderHeight.tsx deleted file mode 100644 index c39ddba7..00000000 --- a/packages/stack/src/utils/useFloatingHeaderHeight.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import * as React from 'react'; -import FloatingHeaderHeightContext from './FloatingHeaderHeightContext'; - -export default function useFloatingHeaderHeight() { - const height = React.useContext(FloatingHeaderHeightContext); - - if (height === undefined) { - throw new Error( - "Couldn't find the floating header height. Are you inside a screen in Stack?" - ); - } - - return height; -} diff --git a/packages/stack/src/utils/useHeaderHeight.tsx b/packages/stack/src/utils/useHeaderHeight.tsx new file mode 100644 index 00000000..6303db3d --- /dev/null +++ b/packages/stack/src/utils/useHeaderHeight.tsx @@ -0,0 +1,14 @@ +import * as React from 'react'; +import HeaderHeightContext from './HeaderHeightContext'; + +export default function useFloatingHeaderHeight() { + const height = React.useContext(HeaderHeightContext); + + if (height === undefined) { + throw new Error( + "Couldn't find the header height. Are you inside a screen in Stack?" + ); + } + + return height; +} diff --git a/packages/stack/src/views/Stack/CardContainer.tsx b/packages/stack/src/views/Stack/CardContainer.tsx index fe3c095d..b4e6b5b6 100644 --- a/packages/stack/src/views/Stack/CardContainer.tsx +++ b/packages/stack/src/views/Stack/CardContainer.tsx @@ -4,7 +4,7 @@ import { StackNavigationState } from '@react-navigation/routers'; import { Route, useTheme } from '@react-navigation/native'; import { Props as HeaderContainerProps } from '../Header/HeaderContainer'; import Card from './Card'; -import FloatingHeaderHeightContext from '../../utils/FloatingHeaderHeightContext'; +import HeaderHeightContext from '../../utils/HeaderHeightContext'; import { Scene, Layout, StackHeaderMode, TransitionPreset } from '../../types'; type Props = TransitionPreset & { @@ -48,7 +48,11 @@ type Props = TransitionPreset & { headerMode: StackHeaderMode; headerShown?: boolean; headerTransparent?: boolean; - floatingHeaderHeight: number; + headerHeight: number; + onHeaderHeightChange: (props: { + route: Route; + height: number; + }) => void; }; export default function CardContainer({ @@ -59,7 +63,6 @@ export default function CardContainer({ cardStyleInterpolator, closing, gesture, - floatingHeaderHeight, focused, gestureDirection, gestureEnabled, @@ -70,6 +73,8 @@ export default function CardContainer({ headerShown, headerStyleInterpolator, headerTransparent, + headerHeight, + onHeaderHeightChange, index, layout, onCloseRoute, @@ -150,7 +155,7 @@ export default function CardContainer({ pointerEvents="box-none" containerStyle={ headerMode === 'float' && !headerTransparent && headerShown !== false - ? { marginTop: floatingHeaderHeight } + ? { marginTop: headerHeight } : null } contentStyle={[{ backgroundColor: colors.background }, cardStyle]} @@ -158,9 +163,9 @@ export default function CardContainer({ > - + {renderScene({ route: scene.route })} - + {headerMode === 'screen' ? renderHeader({ @@ -171,6 +176,7 @@ export default function CardContainer({ state, getPreviousRoute, styleInterpolator: headerStyleInterpolator, + onContentHeightChange: onHeaderHeightChange, }) : null} diff --git a/packages/stack/src/views/Stack/CardStack.tsx b/packages/stack/src/views/Stack/CardStack.tsx index 11337bc8..268a8433 100755 --- a/packages/stack/src/views/Stack/CardStack.tsx +++ b/packages/stack/src/views/Stack/CardStack.tsx @@ -71,7 +71,7 @@ type State = { scenes: Scene>[]; gestures: GestureValues; layout: Layout; - floatingHeaderHeights: Record; + headerHeights: Record; }; const EPSILON = 1e-5; @@ -112,7 +112,7 @@ const MaybeScreen = ({ const FALLBACK_DESCRIPTOR = Object.freeze({ options: {} }); -const getFloatingHeaderHeights = ( +const getHeaderHeights = ( routes: Route[], insets: EdgeInsets, descriptors: StackDescriptorMap, @@ -283,12 +283,12 @@ export default class CardStack extends React.Component { }), gestures, descriptors: props.descriptors, - floatingHeaderHeights: getFloatingHeaderHeights( + headerHeights: getHeaderHeights( props.routes, props.insets, state.descriptors, state.layout, - state.floatingHeaderHeights + state.headerHeights ), }; } @@ -304,7 +304,7 @@ export default class CardStack extends React.Component { // This is not a great heuristic here. We don't know synchronously // on mount what the header height is so we have just used the most // common cases here. - floatingHeaderHeights: {}, + headerHeights: {}, }; private handleLayout = (e: LayoutChangeEvent) => { @@ -319,7 +319,7 @@ export default class CardStack extends React.Component { return { layout, - floatingHeaderHeights: getFloatingHeaderHeights( + headerHeights: getHeaderHeights( props.routes, props.insets, state.descriptors, @@ -330,23 +330,23 @@ export default class CardStack extends React.Component { }); }; - private handleFloatingHeaderLayout = ({ + private handleHeaderLayout = ({ route, height, }: { route: Route; height: number; }) => { - this.setState(({ floatingHeaderHeights }) => { - const previousHeight = floatingHeaderHeights[route.key]; + this.setState(({ headerHeights }) => { + const previousHeight = headerHeights[route.key]; if (previousHeight === height) { return null; } return { - floatingHeaderHeights: { - ...floatingHeaderHeights, + headerHeights: { + ...headerHeights, [route.key]: height, }, }; @@ -375,7 +375,7 @@ export default class CardStack extends React.Component { onPageChangeCancel, } = this.props; - const { scenes, layout, gestures, floatingHeaderHeights } = this.state; + const { scenes, layout, gestures, headerHeights } = this.state; const focusedRoute = state.routes[state.index]; const focusedDescriptor = descriptors[focusedRoute.key]; @@ -521,7 +521,8 @@ export default class CardStack extends React.Component { onPageChangeConfirm={onPageChangeConfirm} onPageChangeCancel={onPageChangeCancel} gestureResponseDistance={gestureResponseDistance} - floatingHeaderHeight={floatingHeaderHeights[route.key]} + headerHeight={headerHeights[route.key]} + onHeaderHeightChange={this.handleHeaderLayout} getPreviousRoute={getPreviousRoute} headerMode={headerMode} headerShown={headerShown} @@ -548,7 +549,7 @@ export default class CardStack extends React.Component { scenes, state, getPreviousRoute, - onContentHeightChange: this.handleFloatingHeaderLayout, + onContentHeightChange: this.handleHeaderLayout, styleInterpolator: focusedOptions.headerStyleInterpolator !== undefined ? focusedOptions.headerStyleInterpolator