mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-04-26 23:06:03 +08:00
feat: add an option to override safe area insets
This commit is contained in:
@@ -5,6 +5,7 @@ import {
|
||||
LayoutChangeEvent,
|
||||
} from 'react-native';
|
||||
import Animated from 'react-native-reanimated';
|
||||
import { EdgeInsets } from 'react-native-safe-area-context';
|
||||
import {
|
||||
NavigationProp,
|
||||
ParamListBase,
|
||||
@@ -207,6 +208,10 @@ export type StackHeaderProps = {
|
||||
* Layout of the screen.
|
||||
*/
|
||||
layout: Layout;
|
||||
/**
|
||||
* Safe area insets to use in the header, e.g. to apply extra spacing for statusbar and notch.
|
||||
*/
|
||||
insets: EdgeInsets;
|
||||
/**
|
||||
* Object representing the current scene, such as the route object and animation progress.
|
||||
*/
|
||||
@@ -302,6 +307,17 @@ export type StackNavigationOptions = StackHeaderOptions &
|
||||
* Defaults to 0.3.
|
||||
*/
|
||||
gestureVelocityImpact?: number;
|
||||
/**
|
||||
* Safe area insets for the screen. This is used to avoid elements like notch and status bar.
|
||||
* By default, the device's safe area insets are automatically detected. You can override the behavior with this option.
|
||||
* For example, to remove the extra spacing for status bar, pass `safeAreaInsets: { top: 0 }`.
|
||||
*/
|
||||
safeAreaInsets?: {
|
||||
top?: number;
|
||||
right?: number;
|
||||
bottom?: number;
|
||||
left?: number;
|
||||
};
|
||||
};
|
||||
|
||||
export type StackNavigationConfig = {
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
import * as React from 'react';
|
||||
import { StackActions } from '@react-navigation/routers';
|
||||
import { useSafeArea } from 'react-native-safe-area-context';
|
||||
|
||||
import HeaderSegment from './HeaderSegment';
|
||||
import { StackHeaderProps, StackHeaderTitleProps } from '../../types';
|
||||
import HeaderTitle from './HeaderTitle';
|
||||
|
||||
export default React.memo(function Header(props: StackHeaderProps) {
|
||||
const insets = useSafeArea();
|
||||
|
||||
const { scene, previous, layout, navigation, styleInterpolator } = props;
|
||||
const {
|
||||
scene,
|
||||
previous,
|
||||
layout,
|
||||
insets,
|
||||
navigation,
|
||||
styleInterpolator,
|
||||
} = props;
|
||||
const { options } = scene.descriptor;
|
||||
const title =
|
||||
typeof options.headerTitle !== 'function' &&
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
ParamListBase,
|
||||
} from '@react-navigation/core';
|
||||
import { StackNavigationState } from '@react-navigation/routers';
|
||||
import { EdgeInsets } from 'react-native-safe-area-context';
|
||||
|
||||
import Header from './Header';
|
||||
import { forStatic } from '../../TransitionConfigs/HeaderStyleInterpolators';
|
||||
@@ -19,6 +20,7 @@ import {
|
||||
export type Props = {
|
||||
mode: 'float' | 'screen';
|
||||
layout: Layout;
|
||||
insets: EdgeInsets;
|
||||
scenes: Array<Scene<Route<string>> | undefined>;
|
||||
state: StackNavigationState;
|
||||
getPreviousRoute: (props: {
|
||||
@@ -36,6 +38,7 @@ export default function HeaderContainer({
|
||||
mode,
|
||||
scenes,
|
||||
layout,
|
||||
insets,
|
||||
state,
|
||||
getPreviousRoute,
|
||||
onContentHeightChange,
|
||||
@@ -87,6 +90,7 @@ export default function HeaderContainer({
|
||||
const props = {
|
||||
mode,
|
||||
layout,
|
||||
insets,
|
||||
scene,
|
||||
previous,
|
||||
navigation: scene.descriptor.navigation as StackNavigationProp<
|
||||
|
||||
@@ -385,7 +385,10 @@ export default class Card extends React.Component<Props> {
|
||||
this.props.current,
|
||||
this.props.next,
|
||||
this.props.layout,
|
||||
this.props.insets
|
||||
this.props.insets.top,
|
||||
this.props.insets.right,
|
||||
this.props.insets.bottom,
|
||||
this.props.insets.left
|
||||
);
|
||||
};
|
||||
|
||||
@@ -684,7 +687,10 @@ export default class Card extends React.Component<Props> {
|
||||
current: Animated.Node<number>,
|
||||
next: Animated.Node<number> | undefined,
|
||||
layout: Layout,
|
||||
insets: EdgeInsets
|
||||
insetTop: number,
|
||||
insetRight: number,
|
||||
insetBottom: number,
|
||||
insetLeft: number
|
||||
) =>
|
||||
styleInterpolator({
|
||||
index,
|
||||
@@ -694,7 +700,12 @@ export default class Card extends React.Component<Props> {
|
||||
layouts: {
|
||||
screen: layout,
|
||||
},
|
||||
insets,
|
||||
insets: {
|
||||
top: insetTop,
|
||||
right: insetRight,
|
||||
bottom: insetBottom,
|
||||
left: insetLeft,
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
@@ -708,7 +719,10 @@ export default class Card extends React.Component<Props> {
|
||||
this.props.current,
|
||||
this.props.next,
|
||||
this.props.layout,
|
||||
this.props.insets
|
||||
this.props.insets.top,
|
||||
this.props.insets.right,
|
||||
this.props.insets.bottom,
|
||||
this.props.insets.left
|
||||
);
|
||||
|
||||
private gestureActivationCriteria() {
|
||||
@@ -776,7 +790,10 @@ export default class Card extends React.Component<Props> {
|
||||
current,
|
||||
next,
|
||||
layout,
|
||||
insets
|
||||
insets.top,
|
||||
insets.right,
|
||||
insets.bottom,
|
||||
insets.left
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -332,6 +332,13 @@ export default class Stack extends React.Component<Props, State> {
|
||||
};
|
||||
}
|
||||
|
||||
const {
|
||||
top = insets.top,
|
||||
right = insets.right,
|
||||
bottom = insets.bottom,
|
||||
left = insets.left,
|
||||
} = focusedOptions.safeAreaInsets || {};
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<MaybeScreenContainer
|
||||
@@ -358,6 +365,7 @@ export default class Stack extends React.Component<Props, State> {
|
||||
: 0;
|
||||
|
||||
const {
|
||||
safeAreaInsets,
|
||||
headerShown,
|
||||
headerTransparent,
|
||||
cardTransparent,
|
||||
@@ -406,6 +414,13 @@ export default class Stack extends React.Component<Props, State> {
|
||||
}
|
||||
}
|
||||
|
||||
const {
|
||||
top: safeAreaInsetTop = insets.top,
|
||||
right: safeAreaInsetRight = insets.right,
|
||||
bottom: safeAreaInsetBottom = insets.bottom,
|
||||
left: safeAreaInsetLeft = insets.left,
|
||||
} = safeAreaInsets || {};
|
||||
|
||||
return (
|
||||
<MaybeScreen
|
||||
key={route.key}
|
||||
@@ -420,12 +435,15 @@ export default class Stack extends React.Component<Props, State> {
|
||||
focused={focused}
|
||||
closing={closingRouteKeys.includes(route.key)}
|
||||
layout={layout}
|
||||
insets={insets}
|
||||
current={current}
|
||||
scene={scene}
|
||||
previousScene={scenes[index - 1]}
|
||||
navigation={navigation}
|
||||
state={state}
|
||||
safeAreaInsetTop={safeAreaInsetTop}
|
||||
safeAreaInsetRight={safeAreaInsetRight}
|
||||
safeAreaInsetBottom={safeAreaInsetBottom}
|
||||
safeAreaInsetLeft={safeAreaInsetLeft}
|
||||
cardTransparent={cardTransparent}
|
||||
cardOverlayEnabled={cardOverlayEnabled}
|
||||
cardShadowEnabled={cardShadowEnabled}
|
||||
@@ -459,6 +477,7 @@ export default class Stack extends React.Component<Props, State> {
|
||||
? renderHeader({
|
||||
mode: 'float',
|
||||
layout,
|
||||
insets: { top, right, bottom, left },
|
||||
scenes,
|
||||
state,
|
||||
getPreviousRoute,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import { View, StyleSheet, StyleProp, ViewStyle } from 'react-native';
|
||||
import Animated from 'react-native-reanimated';
|
||||
import { EdgeInsets } from 'react-native-safe-area-context';
|
||||
import { StackNavigationState } from '@react-navigation/routers';
|
||||
import { Route } from '@react-navigation/core';
|
||||
import { Props as HeaderContainerProps } from '../Header/HeaderContainer';
|
||||
@@ -20,12 +19,15 @@ type Props = TransitionPreset & {
|
||||
focused: boolean;
|
||||
closing: boolean;
|
||||
layout: Layout;
|
||||
insets: EdgeInsets;
|
||||
current: Animated.Value<number>;
|
||||
previousScene?: Scene<Route<string>>;
|
||||
scene: Scene<Route<string>>;
|
||||
state: StackNavigationState;
|
||||
navigation: StackNavigationHelpers;
|
||||
safeAreaInsetTop: number;
|
||||
safeAreaInsetRight: number;
|
||||
safeAreaInsetBottom: number;
|
||||
safeAreaInsetLeft: number;
|
||||
cardTransparent?: boolean;
|
||||
cardOverlayEnabled?: boolean;
|
||||
cardShadowEnabled?: boolean;
|
||||
@@ -96,7 +98,6 @@ export default class StackItem extends React.PureComponent<Props> {
|
||||
const {
|
||||
index,
|
||||
layout,
|
||||
insets,
|
||||
active,
|
||||
focused,
|
||||
closing,
|
||||
@@ -104,6 +105,10 @@ export default class StackItem extends React.PureComponent<Props> {
|
||||
state,
|
||||
scene,
|
||||
previousScene,
|
||||
safeAreaInsetTop,
|
||||
safeAreaInsetRight,
|
||||
safeAreaInsetBottom,
|
||||
safeAreaInsetLeft,
|
||||
cardTransparent,
|
||||
cardOverlayEnabled,
|
||||
cardShadowEnabled,
|
||||
@@ -126,6 +131,13 @@ export default class StackItem extends React.PureComponent<Props> {
|
||||
headerStyleInterpolator,
|
||||
} = this.props;
|
||||
|
||||
const insets = {
|
||||
top: safeAreaInsetTop,
|
||||
right: safeAreaInsetRight,
|
||||
bottom: safeAreaInsetBottom,
|
||||
left: safeAreaInsetLeft,
|
||||
};
|
||||
|
||||
return (
|
||||
<Card
|
||||
index={index}
|
||||
@@ -168,6 +180,7 @@ export default class StackItem extends React.PureComponent<Props> {
|
||||
? renderHeader({
|
||||
mode: 'screen',
|
||||
layout,
|
||||
insets,
|
||||
scenes: [previousScene, scene],
|
||||
state,
|
||||
getPreviousRoute,
|
||||
|
||||
Reference in New Issue
Block a user