react-native-avoid-softinput icon indicating copy to clipboard operation
react-native-avoid-softinput copied to clipboard

AvoidSoftInput.setShouldMimicIOSBehavior(false) causes layout issues on Android

Open wezter96 opened this issue 1 year ago • 16 comments

Environment

Library version: 5.0.0 OS version: Tested on three Android devices with Android 12

The issue seems to be React Native 0.73 specific (0.73.2 is what I have been testing on) The issue did not occur on previous React Native versions.

Feel free to reach out on Discord if you want to discuss the issue: wezter96

Affected platforms

  • [X] Android
  • [ ] iOS

Current behavior

When AvoidSoftInput.setShouldMimicIOSBehavior(false) is triggered, in the return of a useCallback for a useFocusEffect for example it causes a layout push that reduces the space of the content on your screen on the bottom. (If you have a button at the bottom of the screen it will move up slightly, like 20-30px or so)

Expected behavior

Expecting it to work as it has done previously without causing layout changes throughout the app.

Reproduction

I can't share a link for reproduction since it's in a private repository that I am not allowed to share. I understand if that stops you from looking into it.

wezter96 avatar Jan 29 '24 15:01 wezter96

Hi @wezter96, I am unable to investigate without the repro

mateusz1913 avatar Jan 29 '24 16:01 mateusz1913

I'm facing the same issue.

Looks like this library has issues when resetting itself to the status where it was not used before. Both setEnabled(false) and setShouldMimicIOSBehavior(false) are not resetting the App input handlers to their original states, once you use any functions or hooks of this library your App will change some behaviors and even setting them all to false or preventing them to render will not make the App behave the same way it was before using it. The only way to reset it is closing and opening the App again, and avoid rendering the component that uses this library.

It's very strange and I don't know why, and looks like it happens only on Android.

eduardo-santos-tribia avatar Mar 07 '24 11:03 eduardo-santos-tribia

Hey @eduardo-santos-tribia, can you provide link with reproduction?

mateusz1913 avatar Mar 07 '24 17:03 mateusz1913

@mateusz1913 On my side, this function breaks safe area view but I think, it is the same issue as above. https://github.com/TomCorvus/RNSAV

First time, I thought it came from react-navigation, that's why it is installed on the repo, but it causes by setShouldMimicIOSBehavior.

This problem occurs with useAnimatedKeyboard hook of 'react-native-reanimated' too.

TomCorvus avatar Mar 19 '24 15:03 TomCorvus

Hey @TomCorvus I didn't notice you provide a repro, thanks so much!!! I'll try to look into it

mateusz1913 avatar Mar 19 '24 15:03 mateusz1913

Yes, this issue has destroyed my brain. I'm on it since 2 days and on a complex project, I had difficulty finding the problem. It is a pleasure to contribute to resolve this issue. Thanks for your work.

PS: Don't be surprise if you find REA on this repo, I'm using it for the same issue on REA repo.

TomCorvus avatar Mar 19 '24 16:03 TomCorvus

Hey @TomCorvus , I looked at your repro and it seems that the problem is not with SafeAreaView but with StatusBar

https://github.com/mateusz1913/react-native-avoid-softinput/assets/25980166/45d61716-3ada-4d64-817c-6d21503239ae

As you can see, the only change I did in your repro repository is I toggled hidden prop on StatusBar.

From my experience, on Android, the StatusBar works the best, when it's translucent with transparent background. If you hide it, not only it may affect my library, but also SafeAreaView from react-native-safe-area-context and react-native-screens native navigation header may not work properly

Let me know if that resolves your issue 👋

mateusz1913 avatar Mar 21 '24 21:03 mateusz1913

@wezter96 @eduardo-santos-tribia please provide links to reproduction repositories, otherwise I'll close that issue as I'll not be able to investigate it

mateusz1913 avatar Mar 21 '24 21:03 mateusz1913

@mateusz1913 Thanks for your reply. After updating react-native-screens, the problem is fixed for me.

TomCorvus avatar Mar 26 '24 12:03 TomCorvus

Hi, I have got similar problem. I use the hook

export const useSoftKeyboardEffect = () => {
  useFocusEffect(() => {
    AvoidSoftInput.setShouldMimicIOSBehavior(true);
    AvoidSoftInput.setEnabled(true);
     AvoidSoftInput.setAvoidOffset(30);
    AvoidSoftInput.setShowAnimationDelay(0);
    AvoidSoftInput.setShowAnimationDuration(150);
    AvoidSoftInput.setHideAnimationDuration(150);
    AvoidSoftInput.setHideAnimationDelay(0);
    return () => {
      AvoidSoftInput.setAvoidOffset(0);
      AvoidSoftInput.setEnabled(false);
      AvoidSoftInput.setShouldMimicIOSBehavior(false);
    };
  });
};

and bottom sheet implementation from this template

It happens on android only

https://github.com/mateusz1913/react-native-avoid-softinput/assets/66973174/eda144f3-b93c-4b06-beb9-0e80f2618e0c

Jankaz2 avatar Apr 11 '24 17:04 Jankaz2

Hey @Jankaz2, snippet of code is not enough for me to investigate. Pls provide a link to reproduction repository that I can clone and play with

mateusz1913 avatar Apr 11 '24 18:04 mateusz1913

Nah, cannot reproduce that. Idk, maybe the problem is deeper in my project. However, I started using your BottomSheetWrapper instead of useSoftKeyboardEffect and seems working good.

const BottomSheetWrapper = ({ children }: {children: ReactNode}) => {
    return <AvoidSoftInputView style={styles.avoidSoftInputView}>
        {children}
    </AvoidSoftInputView>;
};

Jankaz2 avatar Apr 11 '24 18:04 Jankaz2

👋 also having this issue. we dont have status bar hidden and react-native-screens was updated recently.

skipper09 avatar Jul 18 '24 17:07 skipper09

@mateusz1913 I might have a simpler reprepo to take a look at https://github.com/johnf/rn-avoid-soft-input-bug

Here is a video of what I see untitled.webm

So in this app

  • Home screen doesn't use AvoidSoftInput
  • all other screens do

What you see

  • Screen 1: Looks fine
  • Screen 2: top is hidden
  • Screen 3: Fine
  • Screen 4: Fine
  • Then start hitting back
  • Screen 3: top is hidden
  • Screen 2: top is hidden
  • Screen 1: Fine

Comment out setShouldMimicIOSBehaviour and it works fine.

Adding useSoftInput top the home screen exhibits slightly different behaviour

johnf avatar Aug 19 '24 05:08 johnf

Hey @johnf, first of all thanks so much for solid repro 🚀

I tested this one and was also able to reproduce what you captured in the video recording. The issue in this example is that screens inside of the navigator (HomeScreen, FirstScreen, SecondScreen, ThirdScreen) are not using SafeAreaView from react-native-safe-area-context which is managing the insets on both Android and iOS.

https://github.com/user-attachments/assets/5db462dc-6b76-4e3b-8dbb-6c4702ae634e

After replacing "root container" components in all those screens from <View style={styles.main}> ... </View> to <SafeAreaView style={styles.main}> ... </SafeAreaView> makes the behavior from your video recording not reproducible anymore.

The setShouldMimicIOSBehaviour function under the hood is making the app displaying its content "edge-to-edge" which btw from Android 15 will be the default behavior - if the app is using "edge-to-edge", its content will be drawn under status and navigation bars (similar to how iOS always worked) and that means, to make the UI content in your screens displayed correctly, it needs to be displayed in a container that knows when and how much of safe padding needs to be added - this is where SafeAreaView shines bright 🥳

Let me know, if that works for you, cheers!

mateusz1913 avatar Aug 23 '24 07:08 mateusz1913