react-native-avoid-softinput
react-native-avoid-softinput copied to clipboard
AvoidSoftInput.setShouldMimicIOSBehavior(false) causes layout issues on Android
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.
Hi @wezter96, I am unable to investigate without the repro
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.
Hey @eduardo-santos-tribia, can you provide link with reproduction?
@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.
Hey @TomCorvus I didn't notice you provide a repro, thanks so much!!! I'll try to look into it
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.
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 👋
@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 Thanks for your reply.
After updating react-native-screens
, the problem is fixed for me.
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
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
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>;
};
👋 also having this issue. we dont have status bar hidden and react-native-screens was updated recently.
@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
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!