mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-03-27 22:56:07 +08:00
refactor: don't use keyboardAwareNavigator The HOC currently forces us to expose some options in stack config which we don't want to. So we vendor this functionality for now to avoid this.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import { StackRouter, createNavigator } from '@react-navigation/core';
|
||||
import { createKeyboardAwareNavigator } from '@react-navigation/native';
|
||||
import { Platform } from 'react-native';
|
||||
import StackView from '../views/Stack/StackView';
|
||||
import {
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
NavigationProp,
|
||||
Screen,
|
||||
} from '../types';
|
||||
import KeyboardManager from '../views/KeyboardManager';
|
||||
|
||||
function createStackNavigator(
|
||||
routeConfigMap: {
|
||||
@@ -26,13 +27,19 @@ function createStackNavigator(
|
||||
) {
|
||||
const router = StackRouter(routeConfigMap, stackConfig);
|
||||
|
||||
// Create a navigator with StackView as the view
|
||||
let Navigator = createNavigator(StackView, router, stackConfig);
|
||||
if (!stackConfig.disableKeyboardHandling && Platform.OS !== 'web') {
|
||||
Navigator = createKeyboardAwareNavigator(Navigator, stackConfig);
|
||||
if (stackConfig.disableKeyboardHandling || Platform.OS === 'web') {
|
||||
return createNavigator(StackView, router, stackConfig);
|
||||
}
|
||||
|
||||
return Navigator;
|
||||
return createNavigator(
|
||||
navigatorProps => (
|
||||
<KeyboardManager>
|
||||
{props => <StackView {...props} {...navigatorProps} />}
|
||||
</KeyboardManager>
|
||||
),
|
||||
router,
|
||||
stackConfig
|
||||
);
|
||||
}
|
||||
|
||||
export default createStackNavigator;
|
||||
|
||||
52
packages/stack/src/views/KeyboardManager.tsx
Normal file
52
packages/stack/src/views/KeyboardManager.tsx
Normal file
@@ -0,0 +1,52 @@
|
||||
import * as React from 'react';
|
||||
import { TextInput, Keyboard } from 'react-native';
|
||||
|
||||
type Props = {
|
||||
children: (props: {
|
||||
onPageChangeStart: () => void;
|
||||
onPageChangeConfirm: () => void;
|
||||
onPageChangeCancel: () => void;
|
||||
}) => React.ReactNode;
|
||||
};
|
||||
|
||||
export default class KeyboardManager extends React.Component<Props> {
|
||||
// Numeric id of the previously focused text input
|
||||
// When a gesture didn't change the tab, we can restore the focused input with this
|
||||
private previouslyFocusedTextInput: number | null = null;
|
||||
|
||||
private handlePageChangeStart = () => {
|
||||
const input = TextInput.State.currentlyFocusedField();
|
||||
|
||||
// When a page change begins, blur the currently focused input
|
||||
TextInput.State.blurTextInput(input);
|
||||
|
||||
// Store the id of this input so we can refocus it if change was cancelled
|
||||
this.previouslyFocusedTextInput = input;
|
||||
};
|
||||
|
||||
private handlePageChangeConfirm = () => {
|
||||
Keyboard.dismiss();
|
||||
|
||||
// Cleanup the ID on successful page change
|
||||
this.previouslyFocusedTextInput = null;
|
||||
};
|
||||
|
||||
private handlePageChangeCancel = () => {
|
||||
// The page didn't change, we should restore the focus of text input
|
||||
const input = this.previouslyFocusedTextInput;
|
||||
|
||||
if (input) {
|
||||
TextInput.State.focusTextInput(input);
|
||||
}
|
||||
|
||||
this.previouslyFocusedTextInput = null;
|
||||
};
|
||||
|
||||
render() {
|
||||
return this.props.children({
|
||||
onPageChangeStart: this.handlePageChangeStart,
|
||||
onPageChangeConfirm: this.handlePageChangeConfirm,
|
||||
onPageChangeCancel: this.handlePageChangeCancel,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -46,13 +46,9 @@ type Props = {
|
||||
renderHeader: (props: HeaderContainerProps) => React.ReactNode;
|
||||
renderScene: (props: { route: Route }) => React.ReactNode;
|
||||
headerMode: HeaderMode;
|
||||
onTransitionStart?: (
|
||||
current: { index: number },
|
||||
previous: { index: number }
|
||||
) => void;
|
||||
onGestureBegin?: () => void;
|
||||
onGestureCanceled?: () => void;
|
||||
onGestureEnd?: () => void;
|
||||
onPageChangeStart?: () => void;
|
||||
onPageChangeConfirm?: () => void;
|
||||
onPageChangeCancel?: () => void;
|
||||
};
|
||||
|
||||
type State = {
|
||||
@@ -258,20 +254,10 @@ export default class Stack extends React.Component<Props, State> {
|
||||
}));
|
||||
};
|
||||
|
||||
private handleTransitionStart = ({
|
||||
route,
|
||||
current,
|
||||
previous,
|
||||
}: {
|
||||
route: Route;
|
||||
current: { index: number };
|
||||
previous: { index: number };
|
||||
}) => {
|
||||
const { onTransitionStart, descriptors } = this.props;
|
||||
private handleTransitionStart = ({ route }: { route: Route }) => {
|
||||
const { descriptors } = this.props;
|
||||
const descriptor = descriptors[route.key];
|
||||
|
||||
onTransitionStart && onTransitionStart(current, previous);
|
||||
|
||||
descriptor &&
|
||||
descriptor.options.onTransitionStart &&
|
||||
descriptor.options.onTransitionStart();
|
||||
@@ -300,9 +286,9 @@ export default class Stack extends React.Component<Props, State> {
|
||||
renderHeader,
|
||||
renderScene,
|
||||
headerMode,
|
||||
onGestureBegin,
|
||||
onGestureCanceled,
|
||||
onGestureEnd,
|
||||
onPageChangeStart,
|
||||
onPageChangeConfirm,
|
||||
onPageChangeCancel,
|
||||
} = this.props;
|
||||
|
||||
const { scenes, layout, progress, floatingHeaderHeights } = this.state;
|
||||
@@ -386,9 +372,9 @@ export default class Stack extends React.Component<Props, State> {
|
||||
cardShadowEnabled={cardShadowEnabled}
|
||||
cardStyle={cardStyle}
|
||||
gesturesEnabled={index !== 0 && getGesturesEnabled({ route })}
|
||||
onGestureBegin={onGestureBegin}
|
||||
onGestureCanceled={onGestureCanceled}
|
||||
onGestureEnd={onGestureEnd}
|
||||
onPageChangeStart={onPageChangeStart}
|
||||
onPageChangeConfirm={onPageChangeConfirm}
|
||||
onPageChangeCancel={onPageChangeCancel}
|
||||
gestureResponseDistance={gestureResponseDistance}
|
||||
floatingHeaderHeight={floatingHeaderHeights[route.key]}
|
||||
hasCustomHeader={header === null}
|
||||
|
||||
@@ -33,15 +33,11 @@ type Props = TransitionPreset & {
|
||||
onOpenRoute: (props: { route: Route }) => void;
|
||||
onCloseRoute: (props: { route: Route }) => void;
|
||||
onGoBack: (props: { route: Route }) => void;
|
||||
onTransitionStart?: (props: {
|
||||
route: Route;
|
||||
current: { index: number };
|
||||
previous: { index: number };
|
||||
}) => void;
|
||||
onTransitionStart?: (props: { route: Route }) => void;
|
||||
onTransitionEnd?: (props: { route: Route }) => void;
|
||||
onGestureBegin?: () => void;
|
||||
onGestureCanceled?: () => void;
|
||||
onGestureEnd?: () => void;
|
||||
onPageChangeStart?: () => void;
|
||||
onPageChangeConfirm?: () => void;
|
||||
onPageChangeCancel?: () => void;
|
||||
gestureResponseDistance?: {
|
||||
vertical?: number;
|
||||
horizontal?: number;
|
||||
@@ -68,15 +64,21 @@ export default class StackItem extends React.PureComponent<Props> {
|
||||
};
|
||||
|
||||
private handleTransitionStart = ({ closing }: { closing: boolean }) => {
|
||||
const { index, scene, onTransitionStart, onGoBack } = this.props;
|
||||
const {
|
||||
scene,
|
||||
onTransitionStart,
|
||||
onPageChangeConfirm,
|
||||
onPageChangeCancel,
|
||||
onGoBack,
|
||||
} = this.props;
|
||||
|
||||
onTransitionStart &&
|
||||
onTransitionStart({
|
||||
route: scene.route,
|
||||
previous: { index: closing ? index - 1 : index },
|
||||
current: { index },
|
||||
});
|
||||
if (closing) {
|
||||
onPageChangeConfirm && onPageChangeConfirm();
|
||||
} else {
|
||||
onPageChangeCancel && onPageChangeCancel();
|
||||
}
|
||||
|
||||
onTransitionStart && onTransitionStart({ route: scene.route });
|
||||
closing && onGoBack({ route: scene.route });
|
||||
};
|
||||
|
||||
@@ -96,9 +98,8 @@ export default class StackItem extends React.PureComponent<Props> {
|
||||
cardShadowEnabled,
|
||||
cardStyle,
|
||||
gesturesEnabled,
|
||||
onGestureBegin,
|
||||
onGestureCanceled,
|
||||
onGestureEnd,
|
||||
onPageChangeStart,
|
||||
onPageChangeCancel,
|
||||
gestureResponseDistance,
|
||||
floatingHeaderHeight,
|
||||
hasCustomHeader,
|
||||
@@ -129,9 +130,8 @@ export default class StackItem extends React.PureComponent<Props> {
|
||||
shadowEnabled={cardShadowEnabled}
|
||||
gesturesEnabled={gesturesEnabled}
|
||||
onTransitionStart={this.handleTransitionStart}
|
||||
onGestureBegin={onGestureBegin}
|
||||
onGestureCanceled={onGestureCanceled}
|
||||
onGestureEnd={onGestureEnd}
|
||||
onGestureBegin={onPageChangeStart}
|
||||
onGestureCanceled={onPageChangeCancel}
|
||||
gestureResponseDistance={gestureResponseDistance}
|
||||
transitionSpec={transitionSpec}
|
||||
styleInterpolator={cardStyleInterpolator}
|
||||
|
||||
@@ -16,13 +16,9 @@ type Props = {
|
||||
navigation: NavigationProp;
|
||||
descriptors: SceneDescriptorMap;
|
||||
navigationConfig: NavigationStackConfig;
|
||||
onTransitionStart?: (
|
||||
current: { index: number },
|
||||
previous: { index: number }
|
||||
) => void;
|
||||
onGestureBegin?: () => void;
|
||||
onGestureCanceled?: () => void;
|
||||
onGestureEnd?: () => void;
|
||||
onPageChangeStart?: () => void;
|
||||
onPageChangeConfirm?: () => void;
|
||||
onPageChangeCancel?: () => void;
|
||||
screenProps?: unknown;
|
||||
};
|
||||
|
||||
@@ -275,10 +271,9 @@ class StackView extends React.Component<Props, State> {
|
||||
const {
|
||||
navigation,
|
||||
navigationConfig,
|
||||
onTransitionStart,
|
||||
onGestureBegin,
|
||||
onGestureCanceled,
|
||||
onGestureEnd,
|
||||
onPageChangeStart,
|
||||
onPageChangeConfirm,
|
||||
onPageChangeCancel,
|
||||
} = this.props;
|
||||
|
||||
const { mode = 'card', ...config } = navigationConfig;
|
||||
@@ -298,10 +293,9 @@ class StackView extends React.Component<Props, State> {
|
||||
onGoBack={this.handleGoBack}
|
||||
onOpenRoute={this.handleOpenRoute}
|
||||
onCloseRoute={this.handleCloseRoute}
|
||||
onTransitionStart={onTransitionStart}
|
||||
onGestureBegin={onGestureBegin}
|
||||
onGestureCanceled={onGestureCanceled}
|
||||
onGestureEnd={onGestureEnd}
|
||||
onPageChangeStart={onPageChangeStart}
|
||||
onPageChangeConfirm={onPageChangeConfirm}
|
||||
onPageChangeCancel={onPageChangeCancel}
|
||||
renderHeader={this.renderHeader}
|
||||
renderScene={this.renderScene}
|
||||
headerMode={headerMode}
|
||||
|
||||
Reference in New Issue
Block a user