facebook / react-native

A framework for building native applications using React
https://reactnative.dev
MIT License
119.29k stars 24.35k forks source link

Dimensions.get('window').height not consistent in Android 14 and Android 15 #47080

Open arnoldc opened 1 month ago

arnoldc commented 1 month ago

Description

Hi React Native team

There seems to be issue with the latest Android 15 release,

The Dimensions.get('window').height seems not consistent in the model device Pixel6a , i think its same for other pixel devices which has latest android 15 recently

Android 14 (pixel 6a - emulator) Android 15 (pixel 6a - real device)
Screenshot 2024-10-17 at 3 45 37 PM Screenshot_20241017-154526

I tried using the react native boiler plate which is running on 0.75.4 as you can see the numbers in the screenshot for height are different, so any idea whats causing the issue why Android 15 has different results from android 14, even if their model device is same?

Steps to reproduce

  1. create new project from via npx react-native init projectname and begin running it
  2. Use two android version for this test , particularly use Android 14 Pixel 6A , and another Android 15 Pixel 6A i think any pixel version will do
  3. Add this text as the content <Text style={{ fontSize: 30 }}>HEIGHT: {Dimensions.get('window').height} and begin comparing the two

React Native Version

0.75.4

Affected Platforms

Runtime - Android

Output of npx react-native info

info Fetching system and libraries information...
System:
  OS: macOS 14.2.1
  CPU: (10) arm64 Apple M1 Pro
  Memory: 104.83 MB / 16.00 GB
  Shell:
    version: "5.9"
    path: /bin/zsh
Binaries:
  Node:
    version: 18.17.1
    path: ~/.nvm/versions/node/v18.17.1/bin/node
  Yarn:
    version: 3.6.4
    path: /opt/homebrew/bin/yarn
  npm:
    version: 9.6.7
    path: ~/.nvm/versions/node/v18.17.1/bin/npm
  Watchman:
    version: 2023.07.03.00
    path: /opt/homebrew/bin/watchman
Managers:
  CocoaPods:
    version: 1.14.3
    path: /Users/arnoldcamas/.rbenv/shims/pod
SDKs:
  iOS SDK:
    Platforms:
      - DriverKit 23.5
      - iOS 17.5
      - macOS 14.5
      - tvOS 17.5
      - visionOS 1.2
      - watchOS 10.5
  Android SDK:
    API Levels:
      - "28"
      - "29"
      - "30"
      - "31"
      - "32"
      - "33"
      - "34"
    Build Tools:
      - 29.0.2
      - 30.0.2
      - 30.0.3
      - 31.0.0
      - 32.0.0
      - 33.0.0
      - 33.0.1
      - 34.0.0
    System Images:
      - android-28 | Google APIs ARM 64 v8a
      - android-28 | Google ARM64-V8a Play ARM 64 v8a
      - android-29 | Intel x86 Atom_64
      - android-29 | Google APIs ARM 64 v8a
      - android-29 | Google APIs Intel x86 Atom
      - android-29 | Google Play ARM 64 v8a
      - android-30 | Google APIs ARM 64 v8a
      - android-30 | Google APIs Intel x86_64 Atom
      - android-30 | Google Play ARM 64 v8a
      - android-30 | Google APIs ATD ARM 64 v8a
      - android-30 | Google APIs ATD Intel x86 Atom
      - android-31 | Google APIs ARM 64 v8a
      - android-31 | Google APIs Intel x86_64 Atom
      - android-31 | Google Play ARM 64 v8a
      - android-32 | Google APIs ARM 64 v8a
      - android-33 | Google APIs ARM 64 v8a
      - android-34 | Google Play ARM 64 v8a
      - android-35 | Google APIs ARM 64 v8a
    Android NDK: Not Found
IDEs:
  Android Studio: 2024.1 AI-241.18034.62.2412.12266719
  Xcode:
    version: 15.4/15F31d
    path: /usr/bin/xcodebuild
Languages:
  Java:
    version: 17.0.10
    path: /Users/arnoldcamas/Library/Java/JavaVirtualMachines/corretto-17.0.10/Contents/Home/bin/javac
  Ruby:
    version: 2.7.4
    path: /Users/arnoldcamas/.rbenv/shims/ruby
npmPackages:
  "@react-native-community/cli": Not Found
  react:
    installed: 18.3.1
    wanted: 18.3.1
  react-native:
    installed: 0.75.4
    wanted: 0.75.4
  react-native-macos: Not Found
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: true
  newArchEnabled: false
iOS:
  hermesEnabled: Not found
  newArchEnabled: false

Stacktrace or Logs

none

Reproducer

https://snack.expo.dev/@arnoldc/4dc13a

Screenshots and Videos

No response

arnoldc commented 1 month ago

this below is the Android 15 (pixel 6a) - Emulator version Screenshot 2024-10-17 at 4 12 03 PM but still its same with physical device , but idk why android 14 and android 15 has different height but it same model??

kontea-dev commented 1 month ago

Same for me on Pixel 6 API 34 vs Pixel 6 API 35 Using height from useWindowDimensions() : Pixel 6 API 34 height => 841.5238..... Pixel 6 API 35 height => 914.2857.....

arnoldc commented 1 month ago

not sure but i think it was the bump of height in the bar found in the bottom of devices for pixel devices , idk 🤷 if im correct

I also use the hook useWindowDimensions height value -> e.g const {height, width, scale, fontScale} = useWindowDimensions();

, and the differences is much bigger now , i think there is an issue with calculating the dimension for android 15? any thoughts on this?

cortinico commented 1 month ago

@alanleedev could you take a look at this one when you have a minute?

alanleedev commented 1 month ago

@cortinico This behavior is not well documented but seems like on Android 15 height for window and screen is returning the same. Systems bars appear to be ignored. Emulator screenshots. Left is Android 15 and right is Android 14 on same device type. Looking into fixing this to match existing behavior. Screenshot 2024-10-18 at 12 22 37 AM

alanleedev commented 1 month ago

Although we do not call this directly and is supposed to be deprecated since API 30 but there is some info in Display.getSize() documentation which may be relevant: https://developer.android.com/reference/android/view/Display#getSize(android.graphics.Point)

- API level 35 and above, the window size will be returned.
- API level 34 and below, the window size minus system decoration areas and display cutout is returned.

I guess this could be correct if forced edge-to-edge is enabled. It does seem like same values is returned on Android 15 regardless of it is forced edge-to-edge or not. Seems like it could be bit tricky to handle and not completely sure if this is something we should try to fix.

mahishdino commented 4 weeks ago

What method could replace in place of Display.getSize() method ? If that is the case @alanleedev

arnoldc commented 3 weeks ago

so it seems bug in the api of react-native?, if thats the findings as well hmm what should be the workaround for the meantime

any suggestions?

thanks

alanleedev commented 3 weeks ago

so it seems bug in the api of react-native?, if thats the findings as well hmm what should be the workaround for the meantime

It is not a bug in react-native. It is actually how the Android API works currently. It behaves differently between Android 14 and Android 15. The question is should we do additional work on top of it to make it work like we expect it to. Doing this can get bit tricky is what I meant.

alanleedev commented 3 weeks ago

@mahishdino @arnoldc We do not actually call Display.getSize() directly. I just found hints on what could be happening in its doc. The code that does the widow or screen height calculation is DisplayMetricsHolder.kt.

alanleedev commented 2 weeks ago

We are discussion what we should do about this. Will update once we have direction.

asherLZR commented 2 weeks ago

Hi, thanks for the update. In the meantime, are there any good workarounds? This is impacting the placement of visual elements on our screens.

alanleedev commented 2 weeks ago

Hey folks, I plan to work on a fix to return the expected value. However curious to learn what everyone is using this for to see what kind of workaround we can recommend. @asherLZR @arnoldc

asherLZR commented 2 weeks ago

One example is, in a bottom sheet, the initial position starts off screen at Dimensions.get('window').height. When the content is rendered, it gets translated in up to a maximum height also determined by some calculation based on Dimensions. There are also other gesture-based and scroll-based calculations which rely on a meaningful window height.

asherLZR commented 2 weeks ago

Naively, one approach for a workaround might be to know the height of the gesture bar, then deduct that from Dimensions.get('window').height or Dimensions.get('screen').height for only API 35. However, I'm not sure if this information is available or if the method is robust.

soutua commented 2 weeks ago

The only app side workaround that comes to mind at the moment is not to use the Dimensions API at all, but instead add a full screen absolute view (= having position: 'absolute', top: 0, left: 0, right: 0, bottom: 0) e.g. in the app root that listens for the view's onLayout callback, and store the event.nativeEvent.layout.height reported by the onLayout-event, and use that value instead of the value reported by Dimensions API.

Side note, that same approach works as a workaround also for this issue: https://github.com/facebook/react-native/issues/41918

vytautasvargonas commented 2 weeks ago

interestingly the Android docs imply that the transition should be enabling edge to edge display. However enabling edge-to-edge as per docs still result in different window size depending on OS version. Has anyone found success with it?

dgreasi commented 2 days ago

Having the same issue. Any updates on that?