From a7b40b4835c0754f5f82504459de05c15cc2e510 Mon Sep 17 00:00:00 2001 From: Soon Wang Date: Thu, 25 Jun 2026 14:25:49 +0800 Subject: [PATCH] fix(rn): improve safe area insets handling for Android during initialization --- .../platform/patch/getDefaultOptions.ios.js | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/packages/core/src/platform/patch/getDefaultOptions.ios.js b/packages/core/src/platform/patch/getDefaultOptions.ios.js index a3368d2761..8756725e7a 100644 --- a/packages/core/src/platform/patch/getDefaultOptions.ios.js +++ b/packages/core/src/platform/patch/getDefaultOptions.ios.js @@ -534,6 +534,28 @@ function getLayoutData (headerHeight) { } } +let hasResolvedSafeAreaTop = false + +function getSafeAreaInsetsWithInitialTop (safeAreaInsets) { + if (ReactNative.Platform.OS !== 'android' || hasResolvedSafeAreaTop) { + return safeAreaInsets + } + const initialTop = initialWindowMetrics?.insets?.top || 0 + if (safeAreaInsets?.top === 0 && initialTop) { + // Android 初始化时 top 可能连续为 0(如红米 10 的 bottom 已更新但 top 仍为 0),此时持续兜底并保留其他 insets 的最新值。 + // 返回新对象,避免修改 useSafeAreaInsets/context 返回的引用。 + return { + ...safeAreaInsets, + top: initialTop + } + } + if (safeAreaInsets?.top > 0 || !initialTop) { + // 拿到真实 top 或没有可用初始值后,后续完全使用 useSafeAreaInsets 的更新。 + hasResolvedSafeAreaTop = true + } + return safeAreaInsets +} + export function PageWrapperHOC (WrappedComponent, pageConfig = {}) { return function PageWrapperCom ({ navigation, route, ...props }) { const keyboardAvoidRef = useRef(null) @@ -582,8 +604,8 @@ export function PageWrapperHOC (WrappedComponent, pageConfig = {}) { ) ) } - // android存在第一次打开insets都返回为0情况,后续会触发第二次渲染后正确 - navigation.insets = useSafeAreaInsets() + // Android 初始化期间持续兜底 safe area top,直到 useSafeAreaInsets 返回真实值。 + navigation.insets = getSafeAreaInsetsWithInitialTop(useSafeAreaInsets()) return withKeyboardAvoidingView( createElement(ReactNative.View, {