fix: add special statusbar handling to modal presentation

This commit is contained in:
Satyajit Sahoo
2021-03-12 23:08:13 +01:00
parent 78b00bd814
commit a204edd012
4 changed files with 188 additions and 31 deletions

View File

@@ -160,6 +160,10 @@ export function forModalPresentationIOS({
overflow: 'hidden',
borderTopLeftRadius: borderRadius,
borderTopRightRadius: borderRadius,
// We don't need these for the animation
// But different border radius for corners improves animation perf
borderBottomLeftRadius: isIphoneX() ? borderRadius : 0,
borderBottomRightRadius: isIphoneX() ? borderRadius : 0,
marginTop: index === 0 ? 0 : statusBarHeight,
marginBottom: index === 0 ? 0 : topOffset,
transform: [{ translateY }, { scale }],

View File

@@ -0,0 +1,51 @@
import * as React from 'react';
import { StatusBar, StyleSheet } from 'react-native';
import { useTheme } from '@react-navigation/native';
import type { EdgeInsets } from 'react-native-safe-area-context';
import type { Layout } from '../types';
type Props = {
layout: Layout;
insets: EdgeInsets;
style: any;
};
export default function ModalStatusBarManager({
layout,
insets,
style,
}: Props) {
const { dark } = useTheme();
const [isDark, setIsDark] = React.useState(true);
const flattenedStyle = StyleSheet.flatten(style);
const translateY = flattenedStyle?.transform?.find(
(s: any) => s.translateY !== undefined
)?.translateY;
React.useEffect(() => {
const isLandscape = layout.width > layout.height;
const scale = 1 - 20 / layout.width;
if (dark || isLandscape || !layout.width) {
return;
}
const listener = ({ value }: { value: number }) => {
const isOverlappingStatusBar = value / scale < insets.top / 3;
setIsDark(isOverlappingStatusBar);
};
const sub = translateY?.addListener(listener);
return () => translateY?.removeListener(sub);
}, [dark, insets.top, layout.height, layout.width, translateY]);
if (dark) {
return null;
}
return (
<StatusBar animated barStyle={isDark ? 'dark-content' : 'light-content'} />
);
}

View File

@@ -18,6 +18,8 @@ import {
GestureState,
PanGestureHandlerGestureEvent,
} from '../GestureHandler';
import ModalStatusBarManager from '../ModalStatusBarManager';
import { forModalPresentationIOS } from '../../TransitionConfigs/CardStyleInterpolators';
import CardAnimationContext from '../../utils/CardAnimationContext';
import getDistanceForDirection from '../../utils/getDistanceForDirection';
import getInvertedMultiplier from '../../utils/getInvertedMultiplier';
@@ -523,6 +525,15 @@ export default class Card extends React.Component<Props> {
return (
<CardAnimationContext.Provider value={animationContext}>
{index === 0 &&
next &&
styleInterpolator === forModalPresentationIOS ? (
<ModalStatusBarManager
layout={layout}
insets={insets}
style={cardStyle}
/>
) : null}
<Animated.View
style={{
// This is a dummy style that doesn't actually change anything visually.