react-native-screens icon indicating copy to clipboard operation
react-native-screens copied to clipboard

Fixing Android keyboard adjustResize not working with status bar tran…

Open nikhiltekwani09 opened this issue 1 year ago • 9 comments

…slucent

Description

In android, the adjustResize soft input mode is not working as expected when status bar is set as translucent. react-native version: 0.74.3 react-native-screens version: 3.34.0

Fixes #2308

Changes

  • Fixed an issue with window insets where the keyboard (IME) height was not being accurately calculated.
  • Replaced the old handling of WindowInsetsCompat.Type.statusBars() with a new implementation that includes the keyboard inset (WindowInsetsCompat.Type.ime()).
  • This ensures correct bottom insets handling when the keyboard is open by taking the maximum of the system bars and IME insets.

Example where issue is reproducible - https://github.com/1880akshay/RN_NewArch_TextInput/tree/android-keyboard The change which caused the issue - https://github.com/software-mansion/react-native-screens/commit/52f13c69af80e92fdf7c58aaa9645c4d20aee297

nikhiltekwani09 avatar Aug 21 '24 17:08 nikhiltekwani09

@nikhiltekwani09 I don't think it's a great fix. Adding keyboard insets (i. e. keyboard height) as bottom padding doesn't sound right to me (but it's my personal opinion - I'm not a maintainer of RNS, but I added the code that you are modifying).

Another question - why do we add keyboard insets only to Android R? Prior to that version everything works fine?

I also opened a separate issue in another repository: https://github.com/Expensify/react-native-live-markdown/issues/346

The issue may be different but maybe it can give you some insights into where to search for the problem additionally!

kirillzyusko avatar Aug 22 '24 13:08 kirillzyusko

@kirillzyusko the things were working perfectly prior to android R The commit that generated the issue: https://github.com/software-mansion/react-native-screens/commit/52f13c69af80e92fdf7c58aaa9645c4d20aee297

And I have considered the keyboard height using WindowInsetsCompat.Type.ime() as this gives a non 0 value only when the keyboard is opened and we want the height to decrease equivalent to value of keyboard height when it is opened

nikhiltekwani09 avatar Aug 22 '24 14:08 nikhiltekwani09

Well, my opinion is that it's not a correct approach, because prior to https://github.com/software-mansion/react-native-screens/commit/52f13c69af80e92fdf7c58aaa9645c4d20aee297 we were using only getSystemWindowInsetBottom, right?

If we open a documentation we'll clearly see, that new approach is to use getInsets(WindowInsetsCompat.Type.statusBars()):

image

Now we add ime insets, which I think is not a correct solution, because systemWindowInsetBottom didn't include .ime() insets, but in this PR we start to mix different insets and apply them to a decorView 🤷‍♂️ (so these changes do not look to me as a backward compatible).

Here is the PR that introduced new API for Android 30+: https://github.com/software-mansion/react-native-screens/pull/1868

But again, it's only my opinion - I would wait for a review from maintainers to see what they say 👀

kirillzyusko avatar Aug 22 '24 14:08 kirillzyusko

Yes but that is always returning a 0 value and earlier it was returning the keyboard height Do you suggest any other workaround to fix the issue?

nikhiltekwani09 avatar Aug 22 '24 15:08 nikhiltekwani09

@nikhiltekwani09 well, I checked and it looks like systemWindowInsetBottom indeed includes ime insets. I'm still slightly concerned because the documentation says the opposite (that it includes StatusBar only). And also curious why it happens on Fabric only?

kirillzyusko avatar Aug 23 '24 08:08 kirillzyusko

Yes that is why I manually added ime insets. Also the issue is happening without fabric as well.

nikhiltekwani09 avatar Aug 23 '24 08:08 nikhiltekwani09

@nikhiltekwani09 oh, yeah, I see it now. I think potentially a better option would be to combine insets together without involving math operations:

val windowInsets = defaultInsets.getInsets(WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.ime())
WindowInsetsCompat
    .Builder()
    .setInsets(
        WindowInsetsCompat.Type.systemBars(),
        Insets.of(
            windowInsets.left,
            0,
            windowInsets.right,
          windowInsets.bottom,
        ),
    ).build()

But this is really strange, that Android claims to use systemBars() as a replacement for systemWindowInset*, but systemWindowInset* includes ime insets and systemBars() are not 🤷‍♂️

        /**
         * @return All system bars. Includes {@link #statusBars()}, {@link #captionBar()} as well as
         * {@link #navigationBars()}, but not {@link #ime()}.
         */
        @InsetsType
        public static int systemBars() {
            return STATUS_BARS | NAVIGATION_BARS | CAPTION_BAR;
        }

Anyway I would wait for a review from SWM team 😅

kirillzyusko avatar Aug 23 '24 08:08 kirillzyusko

Yes I would also wait for the comments from the maintainers now

nikhiltekwani09 avatar Aug 23 '24 09:08 nikhiltekwani09

Can we please merge this PR

nikhiltekwani09 avatar Sep 05 '24 18:09 nikhiltekwani09