-
-
Notifications
You must be signed in to change notification settings - Fork 83
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Incorrect KeyboardAvoidingView calculations on Android #334
Comments
Hello @joeporpeglia Thank you for your issue!
This is how original Let's consider a case when you have a view in the top part of the screen and keyboard appears (let's say that in this case only 10px of view will be obscured by keyboard). If you push the view to the entire keyboard height (let's say 336), then a significant part of the view will be obscured by window traits (i. e. status bar) 😓 So I think "relative keyboard height" is a preferred choice in this case. If you clone example app - does the problem happen as well? (If yes, then it explains why I've used |
Thank you for the explanation @kirillzyusko! I tweaked the example app to reproduce the issue and I can confirm that the bottom padding is inconsistent between android devices. See https://github.com/joeporpeglia/react-native-keyboard-controller/tree/keyboard-avoiding-view-repro (Changes to demonstrate the issue in this commit) |
@joeporpeglia and what is the output if you log a height from Also in your screenshots I see a difference in elements positioning:
Maybe you have some ideas how to fix this problem, by the way? I checked FB code - they are sending screen coordinates when keyboard is open/closed (but I thought it's an overkill because we can calculate in on JS). |
Using the following logs in
Device output:
Emulator output:
That gap to the left is due to the notch on my device, but you're right it does seem like the emulator uses a different system UI than the physical device.
I've been using a custom keyboard avoiding view that only uses the keyboard height as bottom padding. This fixes the issue because it avoids |
@joeporpeglia okay, I got you. I'll try to have a look into the issue when I get more free time 👀 One solution I was thinking of is the usage I need to play around with the example that you provided on my device to understand where the calculations are wrong and how to fix them 👍 |
@joeporpeglia As a potential workaround you can try to use In a meantime I'll think what is the best way to solve the problem 🤔 |
Hey @kirillzyusko, the custom On a related note, the |
## 📜 Description Implemented own `useWindowDimensions` hook for Android. ## 💡 Motivation and Context The problem with default implementation of `useWindowDimensions` on Android is that it doesn't work well with `edge-to-edge` mode and you can not retrieve an actual size of the screen. Here is a brief comparison of values captured on my device (Pixel 7 Pro). Translucent `StatusBar`: ```sh height: 867.4285888671875 <- own hook height: 867.4285888671875, y: 0 <- useSafeAreaFrame height: 891.4285714285714 <- Dimensions.get('screen') height: 826.2857142857143 <- Dimensions.get('window') ``` Non translucent `StatusBar`: ```sh height: 867.4285888671875 <- own hook height: 826.2857055664062, y: 41.14285659790039 <- useSafeAreaFrame height: 891.4285714285714 <- Dimensions.get('screen') height: 826.2857142857143 <- Dimensions.get('window') ``` So as you can see it doesn't react properly on the case when `StatusBar` is translucent and reports incorrect values, which later on causes incorrect layout calculation in components like `KeyboardAvoidingView` or `KeyboardAwareScrollView`. Theoretically we could workaround this problem by original `useWindowDimensions().height + StatusBar.currentHeight`, but everything become trickier when we add translucent `navigationBar` (+ translucent `statusBar`): ```sh height: 891.4285888671875 <- own hook height: 891.4285888671875, y: 0 <- useSafeAreaFrame height: 891.4285714285714 <- Dimensions.get('screen') height: 826.2857142857143 <- Dimensions.get('window') ``` In this case derived value `useWindowDimensions().height + StatusBar.currentHeight` (867.4285888671875) still will produce incorrect value and all calculations will be broken. So I decided to create own version of the hook which will cover all the cases. Issue for reference: facebook/react-native#41918 Closes #434 #334 ## 📢 Changelog <!-- High level overview of important changes --> <!-- For example: fixed status bar manipulation; added new types declarations; --> <!-- If your changes don't affect one of platform/language below - then remove this platform/language --> ### JS - export own `useWindowDimensions` hook; - started to use own `useWindowDimensions` in `KeyboardAwareScrollView` and `KeyboardAvoidingView` components; - added mock for `useWindowDimensions` hook as default RN implementation; ### Android - added `WindowDimensionsListener` class; - added `ThemedReactContext.content` extension; - added `ThemedReactContext.setupWindowDimensionListener` extension; ## 🤔 How Has This Been Tested? Tested manually on Pixel 7 Pro (API 34). Tested on CI via e2e (API 28). ## 📸 Screenshots (if appropriate): Pixel 7 Pro (Android 14), `KeyboardAwareScrollView`: ### KeyboardAwareScrollView |Before|After| |-------|-----| |![telegram-cloud-photo-size-2-5429580266013318443-y](https://github.com/kirillzyusko/react-native-keyboard-controller/assets/22820318/4874f962-2726-4cd0-ba96-4b57c076b6f5)|![telegram-cloud-photo-size-2-5429580266013318444-y](https://github.com/kirillzyusko/react-native-keyboard-controller/assets/22820318/28a3b276-f8b7-40fa-a17d-bcc4e58b28b7)| ### KeyboardAvoidingView |Initial|Before|After| |------|------|-----| |![telegram-cloud-photo-size-2-5429580266013318470-y](https://github.com/kirillzyusko/react-native-keyboard-controller/assets/22820318/570d0092-c846-4005-97b0-c596169b91f8)|![telegram-cloud-photo-size-2-5429580266013318469-y](https://github.com/kirillzyusko/react-native-keyboard-controller/assets/22820318/8909fee6-aa42-45a3-87b6-65c59831c703)|![telegram-cloud-photo-size-2-5429580266013318471-y](https://github.com/kirillzyusko/react-native-keyboard-controller/assets/22820318/e64c5dfd-cdc1-4cf5-b731-3a25d3a2fde3)| ## 📝 Checklist - [x] CI successfully passed - [x] I added new mocks and corresponding unit-tests if library API was changed
Should be fixed in |
KeyboardAvoidingView
relies onuseWindowDimensions
to calculate the bottom offset:react-native-keyboard-controller/src/components/KeyboardAvoidingView/index.tsx
Lines 69 to 78 in cb715fe
However,
useWindowDimensions
doesn't account for translucent system UI (e.g. status bar) on all devices/emulators (see discussion in facebook/react-native#33735).This causes inconsistent bottom offsets on certain android devices (I've observed this on a Pixel 5 device, but not on a Pixel 5 emulator). I've worked around this issue by implementing a simpler keyboard avoiding view that directly applies
useReanimatedKeyboardAnimation().height
as bottom padding to an animated view.Is there any reason to calculate the bottom offset as "relative keyboard height" instead of using the current keyboard height directly?
The text was updated successfully, but these errors were encountered: