react-native-safe-area-context icon indicating copy to clipboard operation
react-native-safe-area-context copied to clipboard

SafeAreaView flickers with incorrect initial insets on Android

Open janicduplessis opened this issue 1 year ago • 17 comments

This seems to happen with translucent status bar, when it is initially rendered on app start.

janicduplessis avatar Mar 09 '23 17:03 janicduplessis

Can you provide a minimal repro?

jacobp100 avatar Mar 09 '23 21:03 jacobp100

@jacobp100 I discovered this issue in the expensify app in the PR https://github.com/Expensify/App/pull/15778, will work on getting a minimal repro in the example app soon.

janicduplessis avatar Mar 10 '23 19:03 janicduplessis

Sorry I didn’t realise it was you 🤣 I’m not too familiar with the android side of things. Are the insets available when the view mounts?

jacobp100 avatar Mar 10 '23 19:03 jacobp100

I think they are, but wrongly have a bottom value, which might be what causes the flicker. I noticed by logging initialWindowMetrics. Might be related to the flags the app window has initially.

janicduplessis avatar Mar 10 '23 20:03 janicduplessis

Oh interesting. I wonder if android does the same thing of reporting only the safe area that overlaps with the view itself

jacobp100 avatar Mar 10 '23 21:03 jacobp100

It flickers both android ios, on production build, development build, and inside expo. I use react navigation and only few of my views utilize SafeAreaView.

MichalKrakow avatar Mar 13 '23 14:03 MichalKrakow

It may be connected with this issue - https://github.com/th3rdwave/react-native-safe-area-context/issues/186, which @jacobp100 by some reason closed without explanation on how it could be solved or workarounded.

todorone avatar Mar 15 '23 08:03 todorone

I closed it because there’s not enough information to reproduce it

jacobp100 avatar Mar 15 '23 09:03 jacobp100

I'm seeing the same behavior with "react-native-safe-area-context": "4.2.5" on Android only...

zabojad avatar Mar 15 '23 13:03 zabojad

You need a full repo showing it because the config you put in your android manifest affects the behaviour of the library

jacobp100 avatar Mar 15 '23 13:03 jacobp100

@jacobp100 Interesting! What exact parameters from the Android manifest file do affect the behavior of this lib?

EDIT: what easy changes could I try before following your suggestion of providing a reproducer?

zabojad avatar Mar 15 '23 13:03 zabojad

I don't work on Android anymore - so I don't remember

We have a ticket for this https://github.com/th3rdwave/react-native-safe-area-context/issues/349 - it would be really useful if someone is able to help out with this - because I won't be able to

jacobp100 avatar Mar 15 '23 13:03 jacobp100

@janicduplessis did you manage to fix it? If yes, could you share how you did it?

HenrikZabel avatar Jul 31 '23 16:07 HenrikZabel

Hello guys!

  • Here is an example video, slow down to see what is happening.
  • Layout shift happens on the first and fourth start, there are 4 starts in total.
  • I was never able to replicate the phenomenon in any way at Expo Go.
  • This effect only occurs in final live builds. I used EAS Build / Play Console.
  • I also noticed that if I clear the application data (not the cache, but everything), the first startup is always good.
  • The occurrence of the problem seems to be completely random, sometimes 10 times in a row.
  • @jacobp100 I can give you access to my private repo so you can have test code. There is only one not too complicated screen. Just please let me know if you need it.

Update:

  • I just tested the same app on Android 10 and it doesn't have this problem.
  • By the way, the video was made on Android 14.

In the App.js I use the SafeAreaProvider:

<SafeAreaProvider>
    <HomeScreen onLayout={hideSplashScreen} />
    <StatusBar style="auto" translucent />
</SafeAreaProvider>

The HomeScreen wrapped with SafeAreaView:

<SafeAreaView onLayout={onLayout} style={[styles.flexFit, theme.container]}>
      <ScrollView
        contentContainerStyle={[styles.container]}
        showsVerticalScrollIndicator={false}
        keyboardDismissMode="interactive"
      >
      ...
     </ScrollView>
</SafeAreaView>

https://github.com/th3rdwave/react-native-safe-area-context/assets/18605518/e2df7891-3974-4c31-b575-2c246e3ed862

toviszsolt avatar Mar 21 '24 00:03 toviszsolt

In my case problem was with incorrect initialWindowMetrics from the lib. First render. It get's some safe area insets

insets {"bottom": 24, "left": 0, "right": 0, "top": 38.095237731933594} frame {"height": 852.1904907226562, "width": 411.4285583496094, "x": 0, "y": 38.095237731933594}

Second rerender, after layout

layout {"height": 852.1904907226562, "width": 411.4285583496094, "x": 0, "y": 0}
 LOG  insets {"bottom": 0, "left": 0, "right": 0, "top": 0} frame {"height": 852.1904907226562, "width": 411.4285583496094, "x": 0, "y": 38.095237731933594}

SafeAreaProvider placed almost on the root.

const Providers = ({ children }: PropsWithChildren) => (
 <SafeArea.Provider>
   <GestureHandlerRootView className="flex-1">
     <CacheLibraryProvider>
       <NavigationContainer
         theme={NAVIGATION_THEME}
         onStateChange={onNavigationStateChange}
         ref={setNavigationContainerRef}
       >
         <BottomSheetModalProvider>
           <ModalProvider>
             <NoInternetToast.Provider shouldShow={$$(!$isOnline.value)}>
               <LogoutProvider>{children}</LogoutProvider>
             </NoInternetToast.Provider>
           </ModalProvider>
         </BottomSheetModalProvider>
         <Toast />
       </NavigationContainer>
     </CacheLibraryProvider>
   </GestureHandlerRootView>
   <OrientationLocker orientation="PORTRAIT" />
 </SafeArea.Provider>
);

const App = ({
 isHeadless,
}: {
 /**
  * ios specific props from firebase messaging https://rnfirebase.io/messaging/usage#background-application-state
  */
 isHeadless?: boolean;
}) => {
 useEffect(() => {
   Analytics.triggerEventByName('AppLaunched');
   //TODO: Rewrite the code to avoid using this hack
   void restartWatchIfStarted();

   SplashScreen.hide();
 }, []);

 useAntifraudService();

 if (isHeadless) {
   return null;
 }

 return (
   <Providers>
     <StatusBar backgroundColor={'#151515'} />
     <View className="absolute inset-0 bg-gray-700" />
     <NoInternetToast.Ui />

     <ConditionalRouting />
   </Providers>
 );
};

// eslint-disable-next-line import/no-default-export
export default withIAPContext(Sentry.wrap(App));

XantreDev avatar Mar 29 '24 11:03 XantreDev