mateusz1913 / react-native-avoid-softinput

Native solution for common React Native problem of focused views being covered by soft input view.
https://mateusz1913.github.io/react-native-avoid-softinput/
MIT License
700 stars 17 forks source link

Weird screen behavior when moving from a screen that uses AvoidSoftInput #206

Closed PPHelios closed 5 months ago

PPHelios commented 5 months ago

Environment

Library version: 5.0.0 android : Tested on many devices with same result

Affected platforms

Current behavior

I'm using react native bottom tabs in my app and I'm mainly using your library to avoid the bottom bar moving with keyboard then disappear behavior on android when opening keyboard.

when moving from a screen that uses AvoidSoftInput to another that don't a weird animation happens , same happens when moving to a modal in a stack and back.

I tried enabling the AvoidSoftInput in the App.tsx and all screens with forms with no return functions, and It worked but not for the chat screen as it uses Sticky footer recipe so I had to disable AvoidSoftInput inside thechat screen, but still have the issue when going back to the chats screen, also I don't know if this approach is ok (enabling AvoidSoftInput app wide).

Find below two videos, one from my main app the other from a basic app I created to reproduce this issue.

Thanks in advance

https://github.com/mateusz1913/react-native-avoid-softinput/assets/103271591/fcf3c629-4aa0-4361-8995-df95cbfeee1d

https://github.com/mateusz1913/react-native-avoid-softinput/assets/103271591/251bd732-cf65-4920-8626-ef7ee2bf9563

Expected behavior

smooth transition

Reproduction

https://github.com/PPHelios/Bottom-Tabs-Issue

mateusz1913 commented 5 months ago

Hey @PPHelios, thanks so much for providing good reproduction repository!!!

I have played with the repro and I managed to find why the whole layout jumps when changing tabs. The issue is with the StatusBar not being translucent in your app - add following code in your App.tsx

return (
    <>
      {/* add following RN's status bar */}
      <StatusBar animated translucent backgroundColor="transparent" />
      <NavigationContainer>
        {/* <View style={{height: screenHeight, width}}> */}
        <Tab.Navigator
          screenOptions={{
            tabBarHideOnKeyboard: true,
            // tabBarStyle: { position: 'absolute', borderRadius: 30,marginBottom:20}
          }}>
          <Tab.Screen name="Home" component={Home} />
          <Tab.Screen name="Settings" component={Settings} />
        </Tab.Navigator>
        {/* </View> */}
      </NavigationContainer>
    </>
  );

It will make the app render behind the top status bar on Android. The magic AvoidSoftInput.setShouldMimicIOSBehavior(true) makes your Android app rendered in "edge-to-edge" mode, which will be mandatory from Android 15 (sdk 35). If you'll not make statusbar translucent, then it will make such glitches when enabling/disabling "edge-to-edge" mode (that is done in your Home.tsx when screen is focused/unfocused)

And in case when you'll want to prevent UI in your app to be covered by top statusbar, always use react-native-safe-area-context to add required padding if necessary - in case of using react-navigation with default header, it should already be handled correctly, in case of custom headers, simply pass a custom style to that header which will consist additional padding value based on useSafeAreaInsets hook. In case of bottom tabs in react-navigation, the default tab component should also be handled correctly out-of-the-box, while for custom one, you would have to use the same approach as for custom header.

I tried enabling the AvoidSoftInput in the App.tsx and all screens with forms with no return functions, and It worked but not for the chat screen as it uses Sticky footer recipe so I had to disable AvoidSoftInput inside thechat screen, but still have the issue when going back to the chats screen, also I don't know if this approach is ok (enabling AvoidSoftInput app wide).

To answer that question, I'd say you can move the AvoidSoftInput.setShouldMimicIOSBehavior(true) to your App.tsx and have it always enabled, while AvoidSoftInput.setEnabled(true|false) could stay on a per-screen basis

function App(): React.JSX.Element {
  const {height, width} = useWindowDimensions();
  const [screenHeight, setScreenHeight] = useState(height);
  useLayoutEffect(() => {
    AvoidSoftInput.setShouldMimicIOSBehavior(true); // enable it globally here
  }, []);
  // ...

As this is not a bug in a library, I'll close that issue, but feel free to ask further questions. Cheers!