Skip to content
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

KeyboardAvoidingView has wrong placement with translucent Status Bar #434

Closed
flodlc opened this issue May 8, 2024 · 7 comments · Fixed by #468
Closed

KeyboardAvoidingView has wrong placement with translucent Status Bar #434

flodlc opened this issue May 8, 2024 · 7 comments · Fixed by #468
Assignees
Labels
🤖 android Android specific 🐛 bug Something isn't working 📚 components Anything related to the exported components of this library KeyboardAvoidingView 🧪 Anything related to KeyboardAvoidingView component

Comments

@flodlc
Copy link

flodlc commented May 8, 2024

Describe the bug
I use translucent Status Bar on Android using this code:

    StatusBar.setTranslucent(true);
    StatusBar.setBarStyle("dark-content");
    StatusBar.setBackgroundColor("transparent");

I added navigationBarTranslucent on the KeyboardProvider. It works well when the keyboard is hidden but the height calculation seems wrong with the keyboard open.

Code snippet
Add your code snippet where error has been occurred.

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:

  1. A simple screen with a KeyboardAvoidingView and a text input at the bottom (marginTop: 'auto')
  2. Nothing added in styles.xml
  3. Make the Status bar translucent using this code
    StatusBar.setTranslucent(true);
    StatusBar.setBarStyle("dark-content");
    StatusBar.setBackgroundColor("transparent");
  1. statusBarTranslucent={true} on the KeyboardProvider

Expected behavior
The input should stay at the top of the keyboard

Screenshots
Here is a video
Screen_recording_20240508_192540.webm

Smartphone (please complete the following information):

  • Desktop OS: MacOS
  • Device: Google Pixel 8
  • OS: Android
  • RN version: 0.74.1
  • RN architecture: old
  • JS engine: Hermes
  • Library version: [e.g. 1.11.7]

I tried many differents combination, I still have this gap. The only way to remove it is to use a normal StatusBar.

@kirillzyusko
Copy link
Owner

@flodlc is it related to #334?

Can you try to specify keyboardVerticalOffset={-StatusBar.currentHeight} and see if it fixes the problem?

@kirillzyusko kirillzyusko added 🐛 bug Something isn't working 🤖 android Android specific 📚 components Anything related to the exported components of this library labels May 8, 2024
@flodlc
Copy link
Author

flodlc commented May 8, 2024

Yes, it solves the problem and works exactly how it should !
Should I consider it as a hack that will be fixed or a permanent solution ?
Big thank you for the help !

@kirillzyusko
Copy link
Owner

Should I consider it as a hack that will be fixed or a permanent solution ?

I would say it's a workaround rather than a proper solution. I think the problem comes from the fact that useWindowDimensions

const { height: screenHeight } = useWindowDimensions();

returns wrong screen metrics on Android if status bar is translucent (see facebook/react-native#41918)

So my understanding that it should be fixed in core - I can expose my own useWindowDimensions hook from this package, but I think it's not the responsibility of this package to expose this hook 🙈

@flodlc
Copy link
Author

flodlc commented May 9, 2024

I totally agree with you but also I think that the power of this library is to hide all the mess under the hood and simply make it works magically 🪄. I reported the bug in the thread you mentioned. Hope it's gonna be fixed at the root level asap

@kirillzyusko kirillzyusko added the KeyboardAvoidingView 🧪 Anything related to KeyboardAvoidingView component label May 29, 2024
@hirbod
Copy link
Sponsor Contributor

hirbod commented Jun 3, 2024

We're using useSafeAreaFrame from react-native-context-provider instead, as it reports the correct dimensions. Maybe adding react-native-context-provider as a peer dependency is a good idea? I can't imagine a project in the wild without this package anyway, so it should be a fair ask for the users.

@kirillzyusko
Copy link
Owner

@hirbod I think you meant react-native-safe-area-context?

I kind of agree, that it's hard to imagine a real project without this dependency, but this project already depends on react-native-reanimated, potentially in future will depend on react-native-edge-to-edge (this project doesn't exist yet, but should be a common dependency for all projects that depends on edge-to-edge mode (react-native-bars etc.) and adding even more deps (react-native-safe-area-context) sounds like you will have to install a bunch of other dependencies to use this package 😀

But anyway thank you for the suggestion - I will think about it and how to organize everything better 👍

kirillzyusko added a commit that referenced this issue Jun 13, 2024
## 📜 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
@kirillzyusko
Copy link
Owner

Should be fixed in 1.12.3 🤞

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🤖 android Android specific 🐛 bug Something isn't working 📚 components Anything related to the exported components of this library KeyboardAvoidingView 🧪 Anything related to KeyboardAvoidingView component
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants