Open hyochan opened 5 days ago
Hello @hyochan
When you wrap the app in KeyboardProvider
it automatically moves the app in edge-to-edge
mode and with adjustResize
mode the automatic window resize will not work.
So in your case:
KeyboardProvider
and thus automatic resize stopped to work (edge-to-edge mode + adjustResize)KeyboardAvoidingView
from RN to work on Android (on first video KeyboardAvoidingView
wasn't working and the resize that happened was controlled by Android OS). keyboardOffset
is needed to specify because useWindowDimensions
hook from RN that used inside KeyboardAvoidingView
is buggy when it comes to edge-to-edge
mode.keyboardOffset
is needed because you have a view above the KeyboardAvoidingView
(i. e. header) and you need to add it to offset so that layout of KeyboardAvoidingView
matches to window layout.adjustPan
- in this case you force Android OS to handle the keyboard on OS level. In this case adjustPan
simply does transform: [{ translateY: keyboardHeight }]
on OS level (and it's not highly desired, because your navigation header will be also translated - you can see it on your video).The ways how you can solve your problem:
react-native-keyboard-controller
package (in this case you will have smooth animations on both iOS and Android app), you don't need to write platform-conditional code keyboardOffset
since I use internal hook for window dimensions and everything is handled properly<KeyboardProvider enabled={false}>
and enable it using useKeyboardController
on screens where you want to use them.Let me know if you want me to explain any aspect in more details 🙏
Even when using react-native-keyboard-controller and wrapping the app with KeyboardProvider, the existing KeyboardAvoidingView from react-native should continue to function without issues on Android.
Unfortunately it's not achievable in a current reality. The best thing that you can do is to use KeyboardAvoidingView
from react-native-keyboard-controller
.
@kirillzyusko Thank you so much for the detailed and excellent response. Thanks to your explanation, I have gained a better understanding of your library.
As per your suggestion, I removed the platform-specific code and used the KeyboardAvoidingView
from react-native-keyboard-controller
in this commit: https://github.com/hyochan/react-native-keyboard-controller-issue/commit/01eb988a7543c8f579771020c4b14346add7cbba. I also removed keyboardOffset
. However, as shown in the video below, the input does not rise above the keyboard like it does when using the native React Native KeyboardAvoidingView
. This also needs to be explained.
https://github.com/user-attachments/assets/cd6a8030-cc75-48d8-a10d-c279d92aec9b
Additionally, if you have more references regarding the statement "the useWindowDimensions
hook from React Native, used inside KeyboardAvoidingView
, is buggy when it comes to edge-to-edge," it would be very helpful to me.
Thank you.
Additionally, if you have more references regarding the statement "the useWindowDimensions hook from React Native, used inside KeyboardAvoidingView, is buggy when it comes to edge-to-edge," it would be very helpful to me.
You can read about that for example here - https://github.com/facebook/react-native/issues/41918
As per your suggestion, I removed the platform-specific code and used the KeyboardAvoidingView from react-native-keyboard-controller in this commit: https://github.com/hyochan/react-native-keyboard-controller-issue/commit/01eb988a7543c8f579771020c4b14346add7cbba. I also removed keyboardOffset. However, as shown in the video below, the input does not rise above the keyboard like it does when using the native React Native KeyboardAvoidingView. This also needs to be explained.
I'll check why it happens in nearest time!
Okay @hyochan
Sorry for initial misleading - in your case you should have verticalKeyboardOffset
. Let me slightly dive in the implementation of KeyboardAvoidingView
:
useWindowDimensions
;KeyboardAvoidingView
lives and what it measure.So as you can see you had a difference which is equal to headerHeight
+ statusBarHeight
(depends on whether it's translucent or not).
And this space is roughly equal to the size of your text input - that's why it gets hidden behind the keyboard. In your case you should artificially increase the area of a blue rectangle and you can do that by adding verticalKeyboardOffset
. You can get headerSize
using useHeaderHeight hook. If this space is not enough then you can add + StatusBar.currentHeight
I hope I explained why it doesn't work as you expect 😅
Thank you for providing such a detailed and good quality reproduction example ❤️ Let me know if you have any additional questions - I'll be happy to answer on all of them 😊
@kirillzyusko
Thank you for your efforts. Unfortunately, we are still encountering the same issue on Android. The field animates to the top of the upper side of the keyboard, meaning it remains covered.
We have tested all your solutions, but none of them have worked.
I am quite surprised that this bug exists in React Native. I am considering migrating to Flutter, although it is not an easy decision. Some bugs force you to consider alternatives.
If you have any solution that can be applied with clear steps, we would be very grateful. Eg demo which we can understand your sulution since your last reply is very complicated. Demo code is appreciate.
All our app forms are covered by this bug, and the React Native team remains silent.
@kirillzyusko Thanks for the great explanation 👍👍
No Header | With Header |
---|---|
However, I am still curious why react-native-keyboard-controller
's KeyboardAvoidingView
needs extra headerSize
to keyboardOffset. If you could spot the suspicious sections of the code, I would also like to take a look.
This issue needs to be clearly understood to prevent side effects in other views that use KeyboardAvoidingView
. This could be critical for large applications, as it would require testing every view before integrating react-native-keyboard-controller
. (I understand that we can safely adopt this library by disabling it with <KeyboardProvider enabled={false}>
and selectively enabling it where needed. However, I’m trying to understand the root issue. 🤔)
@beshoo I am not getting your statement.
The field animates to the top of the upper side of the keyboard, meaning it remains covered.
I think this should be explained in more details. Providing some code examples and recordings would be very helpful.
Eg demo which we can understand your sulution since your last reply is very complicated. Demo code is appreciate.
@beshoo you can clone the example app https://github.com/kirillzyusko/react-native-keyboard-controller/tree/main/example and see how everything is handled there. This app has a plenty of use cases and covers almost all basic interactions with the keyboard. If you run the code in example app and it works there, but the same code produces different output in your app - it means that something is misconfigured, and it's easier to fix a misconfiguration rather than switching to a new framework/technology 🤷♂️
If you can replace the code in example app with your own code and the bug persist in example application, then feel to free to open a new issue and I'll be glad to help to resolve the problem.
The field animates to the top of the upper side of the keyboard, meaning it remains covered.
It's very hard to say what exactly causes the problem, because I don't see the code, don't see the output (including view hierarchy) and can not test/interact with this code. If you think it's a problem in this library - feel free to open a new issue with reproduction example and I'll try to do all my best to help you.
However, I am still curious why react-native-keyboard-controller's KeyboardAvoidingView needs extra headerSize to keyboardOffset. If you could spot the suspicious sections of the code, I would also like to take a look.
It's all handled in https://github.com/kirillzyusko/react-native-keyboard-controller/blob/e2198afcf71e9bef79e43bf7a1b2a2f19a8a42a8/src/components/KeyboardAvoidingView/index.tsx#L78-L79
This issue needs to be clearly understood to prevent side effects in other views that use KeyboardAvoidingView. This could be critical for large applications, as it would require testing every view before integrating react-native-keyboard-controller. (I understand that we can safely adopt this library by disabling it with
and selectively enabling it where needed. However, I’m trying to understand the root issue. 🤔)
Well, feel free to correct me here, but I think that verticalOffset
is needed for KeyboardAvoidingView
from RN as well. Basically how KeyboardAvoidingView
works - it measures its dimensions (width/height), then when keyboard is open it understands which part of view is covered by keyboard and changes padding to the same size, so that all the content is visible.
But if some elements are placed above the KeyboardAvoidingView
, then dimensions will be gathered incorrectly and it may lead to a situation, when part of the content is obscured by the keyboard.
In the end I implemented test example and covered it by e2e tests to assure that KeyboardAvoidingView
satisfies to default implementation:
Default KAV | KAV from RNKC |
---|---|
On iOS if you don't specify keyboardVerticalOffset
(i. e. header size) you also will end up in the same situation, when bottom elements will be overlapped by keyboard:
RN | RNKC |
---|---|
So I think that a component from react-native-keyboard-controller
works in the same manner as a default KeyboardAvoidingView
on iOS (and on Android it just re-uses all the logic).
I didn't find time to run your project on iOS - but if you run it with keyboardVerticalOffset={0}
will the input be overlapped by keyboard?
If you want to fully match default keyboard handling from Android, then you can wrap your entire app in KAV
:
<GestureHandlerRootView
style={css`
flex: 1;
`}
>
<RootProvider initialThemeType={localThemeType as ColorSchemeName}>
<KeyboardAvoidingView
behavior="padding"
style={{flex: 1, width: '100%'}}
>
<StatusBarBrightness />
<Layout />
</KeyboardAvoidingView>
</RootProvider>
</GestureHandlerRootView>
Then layout will be measured correctly and you don't need to think about headers and other elements (because all of them will be rendered inside KAV
- KAV
will match window dimensions).
But sometimes having just KeyboardAvoidingView
is not always enough to handle the keyboard in all scenarios, but when you have something on a global level it may be hard to disable that (or it can make your code slightly more complicated). Anyway - feel free to chose what exactly best suitable for your project, but I think wrapping an app in KeyboardAvoidingView
is kind of anti-pattern.
Let me know if you have any other questions - will be happy to answer on them as well! 😊 🙌
Describe the bug Hello, thank you for creating such a great library. I've been using
KeyboardAvoidingView
in React Native for a while, but recently needed the keyboard functionality fromreact-native-keyboard-controller
, which allowed me to implement the keyboard behavior I wanted. I really appreciate your work.However, I encountered an issue where
KeyboardAvoidingView
from the corereact-native
package only causes a side-effect on Android. Specifically, when I wrap my app layout withKeyboardProvider
, theKeyboardAvoidingView
inreact-native
package stops working, but this issue is only happening on Android.It seems like the issue was resolved by setting
padding
instead of leaving thebehavior
asundefined
, and also by providing akeyboardVerticalOffset
, but the exact cause and behavior remain unclear, which leaves me feeling a bit uncertain. I would like to better understand how this change impacts screens whereKeyboardAvoidingView
is already being used. Specifically, I’d like to know what effects this adjustment may have on the existing views, especially in terms of layout shifts or keyboard interaction, and whether this might introduce any potential side effects. Could you explain how this configuration influences the layout and behavior in detail?Code snippet
RootProvider.tsx
_layout.tsx
index.tsx
Repo for reproducing I would be highly appreciate if you can provide repository for reproducing your issue. It can significantly reduce the time for discovering and fixing the problem.
To Reproduce Steps to reproduce the behavior:
bun install
or use your package manager.git checkout 16a313a4d8ae1d4a5fb1cdd07529f440527c3dcb
.react-native-keyboard-controller
and wrapped withKeyboardProvider
and test that keyboard is not showing this time.Expected behavior Even when using
react-native-keyboard-controller
and wrapping the app withKeyboardProvider
, the existingKeyboardAvoidingView
fromreact-native
should continue to function without issues on Android.Screenshots
Video Previews
Initial Commit
https://github.com/user-attachments/assets/44d4d630-d2eb-4a23-80bc-b2e59719f064
Install and wrap with KeyboardProvider
https://github.com/user-attachments/assets/2789ad4d-8c3e-4348-9c05-fedf377f7431
Naive workaround
https://github.com/user-attachments/assets/a4ba161c-eee7-4e17-9a6f-efed71499b25
Test other options with useKeyboardAnimation
https://github.com/user-attachments/assets/b9b4a76c-bddf-44f9-b1e0-4ae2d6e5a55b
Smartphone (please complete the following information):
Additional context N/A