fix: double keyboard height#1131
Merged
kirillzyusko merged 3 commits intomainfrom Sep 25, 2025
Merged
Conversation
Contributor
📊 Package size report
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
📜 Description
Fix the issue with double height when
react-native-keyboard-controllerandreact-native-unistylesused together.💡 Motivation and Context
It turns out that
replaceSystemWindowInsetsmethod 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 callreplaceSystemWindowInsetswe may mess upsystemBarinsets. How? As per Android specification:However when we call
replaceSystemWindowInsetsand keyboard is currently visible (and keyboard is treated as system window inset) then we force-include keyboard insets insystemBar. Whenreact-native-unistylesread system insets they getkeyboardinset instead ofbottom-safe-area. I tried to change a code, but if you even explicitly queryType().navigationBars()then keyboard height still included 🤯Important
The code with
replaceSystemWindowInsetswas added intentionally. Without this code we have a jump that was described in #1013 (comment)So to sum up -
replaceSystemWindowInsetsinterfere withsystemBarinsets (keyboard height becomes included). Initial fix was attempted to make in 5f7d16e (we can not use onlynavBarInsets.bottombecause it will be48when 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:
systemBarsinsets with system values 👍ViewCompat.onApplyWindowInsets(v, adjustedInsets)(it will prevent fake nav bar apdding from being added)However after testing new approach I also realized that e2e tests fails 😡
Turns out the internal implementation of
onApplyWindowInsetsin 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
Android
replaceStatusBarInsetsextension;replaceStatusBarInsetsextension inEdgeToEdgeview.🤔 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)
telegram-cloud-document-2-5379740253873536324.mp4
telegram-cloud-document-2-5379740253873536321.mp4
Android 12 (Pixel 6 Pro, API 31)
Screen.Recording.2025-09-25.at.13.23.46.mov
Screen.Recording.2025-09-25.at.13.25.40.mov
📝 Checklist