nirsky/react-native-size-matters

layout looks different across devices

midimurphdesigns opened this issue · 4 comments

I ran into an issue when making a layout that required a specific height in pixel units for a carousel component (react-native-snap-carousel). Flex and percentage heights didn't work. This layout looked different across devices, so I looked to this package to provide a height measurement that would look the same across all devices. However, I am unable to get the layout to look exactly the same across devices. I have a hunch this is because of top/bottom insets and use of SafeAreaView where the size calculation doesn't factor in the insets. But, I'm not 100% sure on this.

The solution I tried to implement, assuming the layout is different because of top/bottom insets, is to utilize the onLayout prop of the uppermost parent view container, one level under the SafeAreaView, to gather the height of the SafeAreaView. I then divided the height of the SafeAreaView by the device height to get a deviceInsetRatio, somewhere between 0.9 and 1 depending on the device. I then set this to globalState and a globalThis variable, and adjust the height calculation by multiplying the desired size by the deviceInsetRatio. I then plug this new value into the verticalScale function provided by this package. It looks something like this:

onLayout={(event) => {
            const {x, y, width, height} = event.nativeEvent.layout;
            const screenHeight = Dimensions.get('window').height;
            const deviceInsetRatioValue = height / screenHeight;
            // console.log('deviceInsetRatioValue: ', deviceInsetRatioValue);
            globalThis.deviceInsetRatio = deviceInsetRatioValue;
            globalActions.setDeviceInsetRatio(deviceInsetRatioValue);
          }}
export const responsiveSizeHeight = (size, alreadyAdjustedToInsets) => {
  // account for SafeAreView/top and bottom insets
  const {deviceInsetRatio} = globalThis;

  if (!deviceInsetRatio || alreadyAdjustedToInsets) {
    return verticalScale(size);
  } else {
    const adjustedSize = Number(size) * deviceInsetRatio;
    return verticalScale(adjustedSize);
  }
};

The problem is I'm still noticing a slight difference on an apk i built vs the two sims i ran it on, one android and one ios. The two sims produced the exact same result. However, the apk I built and ran on an s9+ shows a different layout, differing by about +10-20 pixel units. If anyone has any insight into why this home screen layout using the carousel component is differing across devices, I'd appreciate your help.

Hey @midimurphdesigns,
I guess this is rather a question than an issue with this lib.
Unfortunately, I don't have experience with the kind of setup you are describing and thus can't suggest a solution.

I'll leave the issue open for now, maybe someone will be able to assist.

@nirsky true, I suppose it turned out to be more of question because I'm unsure of the issue. I thought there is a possibility there is an issue with the size calculations not taking into consideration device insets/SafeAreaView but I'm not 100% sure on that.

The size calculation is based on the screen width and height which are provided by React-Native's Dimensions.get('window').
So yeah, I guess you're right - device insets/SafeAreaView are not taken into consideration.

closing for now due to no engagement.