Closed onitzschke closed 4 years ago
Can you provide more information? What value did the API return vs what was expected, for example.
@hramos Xiaomi Mi A2 lite: Dimensions.get('window').height) => 681 Dimensions.get('screen').height) => 760 StatusBar.currentHeight => 31 Google Pixel 3: Dimensions.get('window').height) => 737.4545454545455 Dimensions.get('screen').height) => 785.4545454545455 StatusBar.currentHeight => 24
Expect Dimensions.get('window').height) === 705 on Xiaomi Mi A2 lite to get the same Layout as on Google Pixel 3.
I believe this is related to issues with Dimensions.get('window')
that I outlined here: https://github.com/facebook/react-native/issues/14887#issuecomment-474455052
Hi I'm seeing the same issue. Dimensions.get('window').height
returns the wrong dimensions for me as well on my Essential Phone.
Dimensions.get('screen').height
: 853.3333333333334
Dimensions.get('window').height
: 759.6666666666666
So I took a screenshot and measured out the pixels. I measured the soft menu bar to be 48 logical pixels. So I expect Dimensions.get('window').height
to return 853.333 - 48 = 805.333 but instead I get 759.666. I don't subtract the status bar height because according to the docs, Dimensions.get('window').height
should include the status bar height if the status bar is translucent, which it is.
Same issue on Mi 8 Lite.
Issue is on the new Samsung s10 model too.
My workaround was to calculate root view height with onLayout.
same on redmi note 7
I fix this like this: Import { Dimensions, StatusBar } from 'react-native';
static height = Platform.OS === 'android' ? Dimensions.get('screen').height - StatusBar.currentHeight : Dimensions.get('window').height;
True on Samsung Galaxy s10 model.
I fix this like this: Import { Dimensions, StatusBar } from 'react-native';
static height = Platform.OS === 'android' ? Dimensions.get('screen').height - StatusBar.currentHeight : Dimensions.get('window').height;
I trying now fix (temporarily)like this: Import { Dimensions, StatusBar } from 'react-native';
static height = Platform.OS === 'android' && Platform.Version > 26 ? Dimensions.get('screen').height - StatusBar.currentHeight : Dimensions.get('window').height;
Same problem with react-native 0.59.9, react 16.8.3
React Native Environment Info: System: OS: Windows 10 CPU: (8) x64 Intel(R) Core(TM) i7-8550U CPU @ 1.80GHz Memory: 1.80 GB / 7.87 GB Binaries: Yarn: 1.16.0 - C:\Users\yossi\AppData\Roaming\npm\yarn.CMD npm: 6.1.0 - C:\Program Files\nodejs\npm.CMD IDEs: Android Studio: Version 3.3.0.0 AI-182.5107.16.33.5314842
Based on the phones I've tested, for devices giving wrong height, Dimensions.get('screen').height is not equal to Dimensions.get('window').height. If StatusBar.currentHeight > 24, we consider that it's a device with a notch Here is a temporary fix that I'm using:
Platform.OS !== 'ios' && Dimensions.get('screen').height !== Dimensions.get('window').height && StatusBar.currentHeight > 24
? Dimensions.get('window').height - StatusBar.currentHeight
: Dimensions.get('window').height
@dhruvdangi exist another case with bottom navigation bar, its can be hid or showed.
Just create something like this in app render function. There's small startup speed impact but solves the height issue
if (this.state.windowHeight === 0) {
return <View onLayout={({ nativeEvent }) => {
const windowHeight = nativeEvent.layout.height;
Defaults.windowHeight = windowHeight;
this.setState({ windowHeight })
}} style={{ flex: 1 }} />
}
You can use the following package to fix this issue: https://github.com/Sunhat/react-native-extra-dimensions-android
Hey there, it looks like there has been no activity on this issue recently. Has the issue been fixed, or does it still require the community's attention? This issue may be closed if no further activity occurs. You may also label this issue as a "Discussion" or add it to the "Backlog" and I will leave it open. Thank you for your contributions.
Dear bot;
As far as I am aware, the problem described here is not solved. I tried to add a label, but couldn't find a way to do that.
Based on the phones I've tested, for devices giving wrong height, Dimensions.get('screen').height is not equal to Dimensions.get('window').height. If StatusBar.currentHeight > 24, we consider that it's a device with a notch Here is a temporary fix that I'm using:
Platform.OS !== 'ios' && Dimensions.get('screen').height !== Dimensions.get('window').height && StatusBar.currentHeight > 24 ? Dimensions.get('window').height - StatusBar.currentHeight : Dimensions.get('window').height
unfortunately this didnt work but i modified your code to work for me
Platform.OS !== 'ios' && Dimensions.get('screen').height !== Dimensions.get('window').height && StatusBar.currentHeight > 24 ? Dimensions.get('screen').height - StatusBar.currentHeight : Dimensions.get('window').height
minus from screen height instead of window
Same issue on OnePlus 7. Even though I appreciate the work done by RN Team, I find the failing of such basic, elementary functionality for so long astonishing. Perhaps the blame is on Android API, I don't know. But it's exasperating.
I solved s10 height issues using this:
const height = Platform.OS === 'android' && Platform.Version > 26 ? ExtraDimensions.getRealWindowHeight() - ExtraDimensions.getSoftMenuBarHeight() - StatusBar.currentHeight
: Dimensions.get('window').height- StatusBar.currentHeight;
I am having the same issue on an iPhone 6 with chrome and safari.
@GalB-TenderMarket what is ExtraDimensions
?
I am having the same issue on an iPhone 6 with chrome and safari.
@GalB-TenderMarket what is
ExtraDimensions
?
react-native-extra-dimensions-android npm package
here is how I worked around this bug
import React, { useState, useContext } from "react";
import { Dimensions, View, LayoutChangeEvent } from "react-native";
export default {
window: {
width: Dimensions.get("window").width,
height: Dimensions.get("window").height,
},
};
const DEFAULT_DIMENSIONS_CONTEXT_VALUE = {
width: Dimensions.get("window").width,
height: Dimensions.get("window").height,
};
const DIMENSIONS_CONTEXT = React.createContext(DEFAULT_DIMENSIONS_CONTEXT_VALUE);
export const DimensionsProvider: React.FC = ({ children }) => {
const [layout, setLayout] = useState(DEFAULT_DIMENSIONS_CONTEXT_VALUE);
const handleLayout = ({ nativeEvent }: LayoutChangeEvent) => {
const { width, height } = nativeEvent.layout;
setLayout({ width, height });
};
return (
<View onLayout={handleLayout} style={{ flex: 1 }}>
<DIMENSIONS_CONTEXT.Provider value={layout}>{children}</DIMENSIONS_CONTEXT.Provider>
</View>
);
};
export const useDimensions = () => {
const dimensions = useContext(DIMENSIONS_CONTEXT);
return dimensions;
};
@wmadfaa That is a workaround for the bug but the bug is still here.
Faced with it. Very unpleasant bug.
I am having this bug too.
Me too..so annoying.
+1
It's work for me, you can try
export const deviceHeight = Dimensions.get('window').height;
export const DEVICE_HEIGHT = Platform.select({
ios: deviceHeight,
android:
StatusBar.currentHeight > 24
? deviceHeight
: deviceHeight - StatusBar.currentHeight,
});
+1
+1 same issue tested on xiaomi mi8(real device) and Pixel 3 XL(simulator) according to my observations related CutoutMode(if CutoutMode statusBar height ignore)
+1
How can I detect that user has software bottom navigation bar?
The workaround by @trongitnlu works for me, but an alternative is to use react-native-safe-area-context and grab the frame width and height from there.
import { useSafeAreaFrame } from 'react-native-safe-area-context';
const Component = props => {
const frame = useSafeAreaFrame();
// frame.height
};
A frame equivalent of withSafeAreaInsets
doesn't seem to exist, but with a class component you could make your own higher-order component or a wrapper like this:
class Component extends React.Component { ... }
const Frame = props => {
const frame = useSafeAreaFrame();
return <Component {...props} height={frame.height} />;
};
or grab directly from SafeAreaFrameContext
class Component extends React.Component {
render() {
return (
<SafeAreaFrameContext.Consumer>
{(frame) => ...}
</SafeAreaFrameContext.Consumer>
);
}
}
Make sure to wrap your root component with SafeAreaProvider
for this to work.
@LenKagamine That's a really elegant solution. Thank you.
The workaround by @trongitnlu works for me, but an alternative is to use react-native-safe-area-context and grab the frame width and height from there.
import { useSafeAreaFrame } from 'react-native-safe-area-context'; const Component = props => { const frame = useSafeAreaFrame(); // frame.height };
A frame equivalent of
withSafeAreaInsets
doesn't seem to exist, but with a class component you could make your own higher-order component or a wrapper like this:class Component extends React.Component { ... } const Frame = props => { const frame = useSafeAreaFrame(); return <Component {...props} height={frame.height} />; };
or grab directly from
SafeAreaFrameContext
class Component extends React.Component { render() { return ( <SafeAreaFrameContext.Consumer> {(frame) => ...} </SafeAreaFrameContext.Consumer> ); } }
Make sure to wrap your root component with
SafeAreaProvider
for this to work.
Appreciate this work around! Closing, feel free to open another issue if this continues to be an issue thanks everyone.
@safaiyeh Workaround isn't fix.
Also @LenKagamine workaround not helpful in my case. I want to know dememsions before any view rendered for use demension in StyleSheet.
Instead that workaround possible to use just View
with onLayout
. But I want to fix instead workarounds.
@safaiyeh With all respects, another workaround is to not use React Native, or change our careers in development. My point is, a workaround is no fix. The bug still exists. Please reopen :-) ﻡﺮﮑﺸﺘﻣ
Looking forward for fixes related to this. I have been testing on a Pixel 5 and got surprised about how terrible the Dimensions and StatusBar components are working.
For starters, the Dimensions API has a different behaviour if the device is in portrait or landscape modes. In portrait, it doesn't seem to account for the status bar height, however, it does include the status bar height in landscape. So the code to get the current screen height has to consider whether or not it is in in portrait or landscape.
Following, the StatusBar API does not update the currentHeight
value on orientation changes, so it stays to w/e orientation the app was opened with. Therefore, we cannot use StatusBar.currentHeight
on devices that have different status bars depending on the orientation. Ultimately, we cannot use neither Dimensions nor StatusBar to get the exact window height.
As a very ugly work around written above, I am using this, but note that the 28 value is just a magic value from my test device that will most likely not work in every device.
// screen height = windowHeight - getMinusHeight(orientation.isPortrait)
const getMinusHeight = (isPortrait) => {
// need this to consider notch-based devices
// update this once RN fixes their height calcs
if(StatusBar.currentHeight > 24){
return isPortrait ? 6 : 28;
}
return StatusBar.currentHeight;
}
I invite you to express your feelings regarding Dimensions module here: https://github.com/react-native-community/discussions-and-proposals/issues/291
Did you try to use Dimensions.get("screen").height instead of Dimensions.get("window").height ?
It fixes my issue on Google Pixel 4a.
@safaiyeh this workaround is clearly not applicable to all projects without big rework. With more and more android devices getting screen notches it is not understandable why this does not have high priority and is left to stay. Furthermore I got the assumption that the wrong screen sizes also affect measureView() calculations for those devices.
/**
* Return the current display metrics that are in effect for this resource
* object. The returned object should be treated as read-only.
*
* <p>Note that the reported value may be different than the window this application is
* interested in.</p>
*
* <p>Best practices are to obtain metrics from {@link WindowManager#getCurrentWindowMetrics()}
* for window bounds, {@link Display#getRealMetrics(DisplayMetrics)} for display bounds and
* obtain density from {@link Configuration#densityDpi}. The value obtained from this API may be
* wrong if the {@link Resources} is from the context which is different than the window is
* attached such as {@link Application#getResources()}.
* <p/>
*
* @return The resource's current display metrics.
*/
public DisplayMetrics getDisplayMetrics() {
return mResourcesImpl.getDisplayMetrics();
}
It seems like Dimensions.get('window').height
doesn't include StatusBar.currentHeight
when StatusBar.currentHeight
is >24, giving inconsistent results. Dimensions.get('screen').height
(screen instead of width) is also unpredictable. For me, this always had an excess of 48, maybe equivalent to the Android bottom navigation buttons.
You can see how these dimensions given are incorrect with the following example at the root of the app:
<View style={{
flex: 1,
backgroundColor: 'red'
}}>
<View style={{
width: Dimensions.get('window').width - 2,
height: Dimensions.get('window').height - 2,
backgroundColor: 'blue',
borderWidth: 1,
borderColor: 'yellow'
}}/>
</View>
If all the dimensions given were correct, the blue section would perfectly cover the screen, with a 1px yellow border. This is rarely the case - and there is lots of red space visible, or no yellow, inconsistent between devices.
The dimensions module probably has to be externalized since its been almost a year and this is still broken.
I saw useWindowDimensions() from 'react-native' recommended as the way forward and just migrated to this, but this has the same issue...
Based on the phones I've tested, for devices giving wrong height, Dimensions.get('screen').height is not equal to Dimensions.get('window').height. If StatusBar.currentHeight > 24, we consider that it's a device with a notch Here is a temporary fix that I'm using:
Platform.OS !== 'ios' && Dimensions.get('screen').height !== Dimensions.get('window').height && StatusBar.currentHeight > 24 ? Dimensions.get('window').height - StatusBar.currentHeight : Dimensions.get('window').height
unfortunately this didnt work but i modified your code to work for me
Platform.OS !== 'ios' && Dimensions.get('screen').height !== Dimensions.get('window').height && StatusBar.currentHeight > 24 ? Dimensions.get('screen').height - StatusBar.currentHeight : Dimensions.get('window').height
minus from screen height instead of window
This didn't work for me for few Android devices.
e.g. Xiaomi Redmi 4A: Dimensions.get('screen').height - 640 Dimensions.get('window').height - 640 Status bar height - 25 but REAL Dimensions.get('window').height should be 640-25 = 615 instead of 640!
I have not tested the code below on absolutely all Android devices, so I cannot give a 100% guarantee that this code works on 100% of devices in the world, but it works on all devices that I tested:
import { getStatusBarHeight } from 'react-native-status-bar-height'
import { initialWindowMetrics } from 'react-native-safe-area-context'
export const STATUS_BAR_HEIGHT = getStatusBarHeight()
export const WINDOW_HEIGHT_NO_STATUS_BAR = Platform.OS !== 'ios' && Dimensions.get('screen').height !== Dimensions.get('window').height && STATUS_BAR_HEIGHT > 24
? Dimensions.get('screen').height - STATUS_BAR_HEIGHT
: STATUS_BAR_HEIGHT > 24
? Dimensions.get('window').height - STATUS_BAR_HEIGHT
: Dimensions.get('window').height + initialWindowMetrics.insets.bottom === Dimensions.get('screen').height
? Dimensions.get('window').height - STATUS_BAR_HEIGHT
: Dimensions.get('window').height
Based on the phones I've tested, for devices giving wrong height, Dimensions.get('screen').height is not equal to Dimensions.get('window').height. If StatusBar.currentHeight > 24, we consider that it's a device with a notch Here is a temporary fix that I'm using:
Platform.OS !== 'ios' && Dimensions.get('screen').height !== Dimensions.get('window').height && StatusBar.currentHeight > 24 ? Dimensions.get('window').height - StatusBar.currentHeight : Dimensions.get('window').height
unfortunately this didnt work but i modified your code to work for me
Platform.OS !== 'ios' && Dimensions.get('screen').height !== Dimensions.get('window').height && StatusBar.currentHeight > 24 ? Dimensions.get('screen').height - StatusBar.currentHeight : Dimensions.get('window').height
minus from screen height instead of windowThis didn't work for me for few Android devices.
e.g. Xiaomi Redmi 4A: Dimensions.get('screen').height - 640 Dimensions.get('window').height - 640 Status bar height - 25 but REAL Dimensions.get('window').height should be 640-25 = 615 instead of 640!
I have not tested the code below on absolutely all Android devices, so I cannot give a 100% guarantee that this code works on 100% of devices in the world, but it works on all devices that I tested:
import { getStatusBarHeight } from 'react-native-status-bar-height' import { initialWindowMetrics } from 'react-native-safe-area-context' export const STATUS_BAR_HEIGHT = getStatusBarHeight() export const WINDOW_HEIGHT_NO_STATUS_BAR = Platform.OS !== 'ios' && Dimensions.get('screen').height !== Dimensions.get('window').height && STATUS_BAR_HEIGHT > 24 ? Dimensions.get('screen').height - STATUS_BAR_HEIGHT : STATUS_BAR_HEIGHT > 24 ? Dimensions.get('window').height - STATUS_BAR_HEIGHT : Dimensions.get('window').height + initialWindowMetrics.insets.bottom === Dimensions.get('screen').height ? Dimensions.get('window').height - STATUS_BAR_HEIGHT : Dimensions.get('window').height
I tried this, but unfortunately doesn't quite work always.
Only thing that seems tried and true is:
import { useSafeAreaFrame } from 'react-native-safe-area-context';
I tried this, but unfortunately doesn't quite work always. Could you tell please what are these real devices models?
🐛 Bug Report
Dimensions.get('window').height returns wrong height on Android with notch Device: Android One Mi A2 Lite
Environment
React Native Environment Info: System: OS: macOS 10.14.3 CPU: (12) x64 Intel(R) Core(TM) i7-8850H CPU @ 2.60GHz Memory: 1013.34 MB / 16.00 GB Shell: 5.3 - /bin/zsh Binaries: Node: 11.6.0 - /usr/local/bin/node Yarn: 1.7.0 - /usr/local/bin/yarn npm: 6.8.0 - /usr/local/bin/npm Watchman: 4.9.0 - /usr/local/bin/watchman SDKs: Android SDK: API Levels: 18, 23, 25, 26, 27, 28 Build Tools: 19.1.0, 20.0.0, 21.1.2, 22.0.1, 23.0.1, 23.0.2, 23.0.3, 24.0.0, 24.0.1, 24.0.2, 24.0.3, 25.0.0, 25.0.1, 25.0.2, 25.0.3, 26.0.0, 26.0.1, 26.0.2, 26.0.3, 27.0.0, 27.0.1, 27.0.2, 27.0.3, 28.0.0, 28.0.0, 28.0.0, 28.0.1, 28.0.2, 28.0.3 System Images: android-21 | Intel x86 Atom, android-21 | Google APIs Intel x86 Atom, android-23 | Google APIs Intel x86 Atom, android-23 | Google APIs Intel x86 Atom_64, android-25 | Google APIs ARM EABI v7a, android-27 | Google APIs Intel x86 Atom, android-28 | Google Play Intel x86 Atom, android-28 | Google Play Intel x86 Atom_64 IDEs: Android Studio: 3.3 AI-182.5107.16.33.5264788 Xcode: /undefined - /usr/bin/xcodebuild npmPackages: react: 16.8.3 => 16.8.3 react-native: ^0.58.5 => 0.58.5 npmGlobalPackages: create-react-native-app: 2.0.2 react-native-cli: 2.0.1 react-native-git-upgrade: 0.2.7