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 18 forks source link

AvoidSoftInput.setShouldMimicIOSBehavior(false) causes layout issues on Android #200

Open wezter96 opened 7 months ago

wezter96 commented 7 months ago

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

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.

mateusz1913 commented 7 months ago

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

eduardo-santos-tribia commented 6 months ago

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.

mateusz1913 commented 6 months ago

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

TomCorvus commented 6 months ago

@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.

mateusz1913 commented 6 months ago

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

TomCorvus commented 6 months ago

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.

mateusz1913 commented 6 months ago

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 commented 6 months ago

@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

TomCorvus commented 5 months ago

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

Jankaz2 commented 5 months ago

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

mateusz1913 commented 5 months ago

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

Jankaz2 commented 5 months ago

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>;
};
skipper09 commented 2 months ago

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

johnf commented 1 month ago

@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

What you see

Comment out setShouldMimicIOSBehaviour and it works fine.

Adding useSoftInput top the home screen exhibits slightly different behaviour

mateusz1913 commented 3 weeks ago

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!

johnf commented 3 weeks ago

@mateusz1913 Thanks that did the trick