Commit 0a97fd6
authored
fix: double keyboard height (#1131)
## 📜 Description
Fix the issue with double height when `react-native-keyboard-controller`
and `react-native-unistyles` used together.
## 💡 Motivation and Context
It turns out that `replaceSystemWindowInsets` method is deprecated on
Android. In fact it also overwrite Android behavior. Starting from API
30+ all insets are divided into categories: nav bar insets, status bar
insets, keyboard insets etc. When we call `replaceSystemWindowInsets` we
may mess up `systemBar` insets. How? As per Android specification:
> The status bar, caption bar, and navigation bar are called the system
bars.
However when we call `replaceSystemWindowInsets` and keyboard is
currently visible (and keyboard is treated as system window inset) then
we force-include keyboard insets in `systemBar`. When
`react-native-unistyles` read system insets they get `keyboard` inset
instead of `bottom-safe-area`. I tried to change a code, but if you even
explicitly query `Type().navigationBars()` then keyboard height still
included 🤯
> [!IMPORTANT]
> The code with `replaceSystemWindowInsets` was added intentionally.
Without this code we have a jump that was described in
#1013 (comment)
So to sum up - `replaceSystemWindowInsets` interfere with `systemBar`
insets (keyboard height becomes included). Initial fix was attempted to
make in
5f7d16e
(we can not use only `navBarInsets.bottom` because it will be `48` when
edge-to-edge mode gets disabled, so whole screen container gets pushed
up and we have empty view in bottom of the screen). In this case we
limit system inset to be only bottom tab bar when our view is active and
we pass whole system inset when view is disabled (so that Android
handles everything correctly/fallbacks to its default behavior).
However then I realized, that e2e tests are failing (basically when
keyboard disappear on Android 28 we don't receive onEnd event or receive
it with coordinates as keyboard would be open). I thought that it stems
from the fact that we are using a deprecated API so I re-worked code in
02f76f3
- it uses modern API, but the fix is very similar to what we had before:
- first of all we don't overwrite bottom `systemBars` insets with system
values 👍
- we need to call `ViewCompat.onApplyWindowInsets(v, adjustedInsets)`
(it will prevent fake nav bar apdding from being added)
- we need to replicate the fix when module is disabled - in this case
pass system insets so system will push the content up
However after testing new approach I also realized that e2e tests fails
😡
Turns out the internal implementation of `onApplyWindowInsets` in compat
layer is different, and the easiest fix is to add conditional code, that
will run old code for API < 30 and will run new code for APIs > 30.
Since the new code was getting bigger and bigger I decided to move it
into separate extension where I'm managing all these conditions. That
code is complicated, but this is the only one reliable way I found to
fix client project + not break example app 😓
## 📢 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 -->
### Android
- created `replaceStatusBarInsets` extension;
- use `replaceStatusBarInsets` extension in `EdgeToEdge` view.
## 🤔 How Has This Been Tested?
Tested in client project on: API 29, API 30, API 31, API 33. Tested
example project on API 28 (real device), API 33, API 36 (real device).
## 📸 Screenshots (if appropriate):
### Android 16 (Pixel 7 Pro)
|Before|After|
|------|------|
|<video
src="https://github.com/user-attachments/assets/ed76af1b-ac64-4f67-836c-b441ea173423">|<video
src="https://github.com/user-attachments/assets/37b17239-6edb-41a2-94f4-8e08e347317c">|
### Android 12 (Pixel 6 Pro, API 31)
|Before|After|
|------|------|
|<video
src="https://github.com/user-attachments/assets/e232b66c-3cb6-46c0-9ef6-3baf0aa0c44e">|<video
src="https://github.com/user-attachments/assets/1d336bf7-d9f1-4e35-96a1-d3b9729f04bd">|
## 📝 Checklist
- [x] CI successfully passed
- [x] I added new mocks and corresponding unit-tests if library API was
changed1 parent ad76c6a commit 0a97fd6
3 files changed
Lines changed: 44 additions & 9 deletions
File tree
- .github/workflows
- android/src/main/java/com/reactnativekeyboardcontroller
- extensions
- views
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
80 | 80 | | |
81 | 81 | | |
82 | 82 | | |
83 | | - | |
| 83 | + | |
84 | 84 | | |
85 | 85 | | |
86 | 86 | | |
| |||
Lines changed: 41 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
7 | 10 | | |
8 | 11 | | |
9 | 12 | | |
| |||
58 | 61 | | |
59 | 62 | | |
60 | 63 | | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
Lines changed: 2 additions & 8 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
14 | 14 | | |
15 | 15 | | |
16 | 16 | | |
| 17 | + | |
17 | 18 | | |
18 | 19 | | |
19 | 20 | | |
| |||
130 | 131 | | |
131 | 132 | | |
132 | 133 | | |
133 | | - | |
134 | | - | |
135 | | - | |
136 | | - | |
137 | | - | |
138 | | - | |
139 | | - | |
140 | | - | |
| 134 | + | |
141 | 135 | | |
142 | 136 | | |
143 | 137 | | |
| |||
0 commit comments