feat: add on transition end callback (#153)

This commit is contained in:
Michał Osadnik
2019-07-07 13:02:48 +01:00
committed by satyajit.happy
parent fb9dbf9820
commit 51b1069d51
4 changed files with 61 additions and 24 deletions

View File

@@ -108,6 +108,8 @@ export type NavigationStackOptions = HeaderOptions &
horizontal?: number;
};
disableKeyboardHandling?: boolean;
onTransitionStart?: () => void;
onTransitionEnd?: () => void;
};
export type NavigationConfig = {

View File

@@ -46,8 +46,8 @@ type Props = {
renderScene: (props: { route: Route }) => React.ReactNode;
headerMode: HeaderMode;
onTransitionStart?: (
curr: { index: number },
prev: { index: number }
current: { index: number },
previous: { index: number }
) => void;
onGestureBegin?: () => void;
onGestureCanceled?: () => void;
@@ -60,7 +60,7 @@ type State = {
scenes: HeaderScene<Route>[];
progress: ProgressValues;
layout: Layout;
floaingHeaderHeight: number;
floatingHeaderHeight: number;
};
const dimensions = Dimensions.get('window');
@@ -171,7 +171,7 @@ export default class Stack extends React.Component<Props, State> {
// 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.
floaingHeaderHeight: getDefaultHeaderHeight(layout),
floatingHeaderHeight: getDefaultHeaderHeight(layout),
};
private handleLayout = (e: LayoutChangeEvent) => {
@@ -192,11 +192,32 @@ export default class Stack extends React.Component<Props, State> {
private handleFloatingHeaderLayout = (e: LayoutChangeEvent) => {
const { height } = e.nativeEvent.layout;
if (height !== this.state.floaingHeaderHeight) {
this.setState({ floaingHeaderHeight: height });
if (height !== this.state.floatingHeaderHeight) {
this.setState({ floatingHeaderHeight: height });
}
};
private handleTransitionStart = ({
route,
current,
previous,
}: {
route: Route;
current: { index: number };
previous: { index: number };
}) => {
const { onTransitionStart, descriptors } = this.props;
const options = descriptors[route.key].options;
onTransitionStart && onTransitionStart(current, previous);
options.onTransitionStart && options.onTransitionStart();
};
private handleTransitionEnd = ({ route }: { route: Route }) => {
const options = this.props.descriptors[route.key].options;
options.onTransitionEnd && options.onTransitionEnd();
};
render() {
const {
mode,
@@ -212,13 +233,12 @@ export default class Stack extends React.Component<Props, State> {
renderHeader,
renderScene,
headerMode,
onTransitionStart,
onGestureBegin,
onGestureCanceled,
onGestureEnd,
} = this.props;
const { scenes, layout, progress, floaingHeaderHeight } = this.state;
const { scenes, layout, progress, floatingHeaderHeight } = this.state;
const focusedRoute = navigation.state.routes[navigation.state.index];
const focusedOptions = descriptors[focusedRoute.key].options;
@@ -300,7 +320,7 @@ export default class Stack extends React.Component<Props, State> {
onGestureCanceled={onGestureCanceled}
onGestureEnd={onGestureEnd}
gestureResponseDistance={gestureResponseDistance}
floaingHeaderHeight={floaingHeaderHeight}
floatingHeaderHeight={floatingHeaderHeight}
hasCustomHeader={header === null}
getPreviousRoute={getPreviousRoute}
headerMode={headerMode}
@@ -309,7 +329,8 @@ export default class Stack extends React.Component<Props, State> {
renderScene={renderScene}
onOpenRoute={onOpenRoute}
onCloseRoute={onCloseRoute}
onTransitionStart={onTransitionStart}
onTransitionStart={this.handleTransitionStart}
onTransitionEnd={this.handleTransitionEnd}
onGoBack={onGoBack}
direction={direction}
transitionSpec={transitionSpec}

View File

@@ -33,10 +33,12 @@ type Props = TransitionPreset & {
onOpenRoute: (props: { route: Route }) => void;
onCloseRoute: (props: { route: Route }) => void;
onGoBack: (props: { route: Route }) => void;
onTransitionStart?: (
curr: { index: number },
prev: { index: number }
) => void;
onTransitionStart?: (props: {
route: Route;
current: { index: number };
previous: { index: number };
}) => void;
onTransitionEnd?: (props: { route: Route }) => void;
onGestureBegin?: () => void;
onGestureCanceled?: () => void;
onGestureEnd?: () => void;
@@ -46,22 +48,34 @@ type Props = TransitionPreset & {
};
headerMode: HeaderMode;
headerTransparent?: boolean;
floaingHeaderHeight: number;
floatingHeaderHeight: number;
hasCustomHeader: boolean;
};
export default class StackItem extends React.PureComponent<Props> {
private handleOpen = () =>
this.props.onOpenRoute({ route: this.props.scene.route });
private handleOpen = () => {
const { scene, onTransitionEnd, onOpenRoute } = this.props;
private handleClose = () =>
this.props.onCloseRoute({ route: this.props.scene.route });
onTransitionEnd && onTransitionEnd({ route: scene.route });
onOpenRoute({ route: scene.route });
};
private handleClose = () => {
const { scene, onTransitionEnd, onCloseRoute } = this.props;
onTransitionEnd && onTransitionEnd({ route: scene.route });
onCloseRoute({ route: scene.route });
};
private handleTransitionStart = ({ closing }: { closing: boolean }) => {
const { index, scene, onTransitionStart, onGoBack } = this.props;
onTransitionStart &&
onTransitionStart({ index: closing ? index - 1 : index }, { index });
onTransitionStart({
route: scene.route,
previous: { index: closing ? index - 1 : index },
current: { index },
});
closing && onGoBack({ route: scene.route });
};
@@ -86,7 +100,7 @@ export default class StackItem extends React.PureComponent<Props> {
onGestureCanceled,
onGestureEnd,
gestureResponseDistance,
floaingHeaderHeight,
floatingHeaderHeight,
hasCustomHeader,
getPreviousRoute,
headerMode,
@@ -126,7 +140,7 @@ export default class StackItem extends React.PureComponent<Props> {
pointerEvents="box-none"
containerStyle={
headerMode === 'float' && !headerTransparent && !hasCustomHeader
? { marginTop: floaingHeaderHeight }
? { marginTop: floatingHeaderHeight }
: null
}
contentStyle={cardStyle}

View File

@@ -19,8 +19,8 @@ type Props = {
descriptors: Descriptors;
navigationConfig: NavigationConfig;
onTransitionStart?: (
curr: { index: number },
prev: { index: number }
current: { index: number },
previous: { index: number }
) => void;
onGestureBegin?: () => void;
onGestureCanceled?: () => void;