man zet
man zet

Reputation: 901

React Native: Android not setting width and height correct []

A very simple View:

import React from "react";
import { View } from "react-native";

export default function App() {
  return (
    <View
      onLayout={(layout) => {
        console.log(layout.nativeEvent);
      }}
      style={{
        width: 371,
        height: 477,
      }}
    ></View>
  );
}

So I'm just making a view with width=371 and height=477 and then log its layout. When I run this with expo on my actual iPhone 5s device I get the following output:

{
  "layout": Object {
    "height": 477,
    "width": 371,
    "x": 0,
    "y": 0,
  },
  "target": 3,
}

which is correct. But when i run it on an android pixel 2 emulator with screen size 1080x1920:420dpi (I don't have an actual android device) I get the following output:

Object {
  "layout": Object {
    "height": 476.952392578125,
    "width": 371.047607421875,
    "x": 0,
    "y": 0,
  },
  "target": 3,
}

So width and height are slightly of. Normally I would say this doesn't really matter this much because it is less then one pixel but the problem is that for my application this seems to lead to very ugly looking display errors, where some tiles that should fit seamlessly together having some very small margin:

enter image description here

Actually I'm not a hundred percent sure if this is the reason. However, it seems to me as a very suspicious candidate. Any idea how to fix this?

Edit:

Some more detail to reproduce the the pixel interpolation error in the image. As I said the promblem decribed in this post is what to me seems to be the reason for causing this but I'm not hundret percent sure. In all cases, however, the scenario described above is very strange.

So for the following code (a grid of 7x9 53pixel large views that should add seamlessly together):

import React from "react";
import { View } from "react-native";

export default function App() {
  let cell_size = 53;
  let width = 7;
  let height = 9;

  let rows = [];
  for (let i = 0; i < height; i++) {
    let row_elms = [];
    for (let j = 0; j < width; j++) {
      row_elms.push(
        <View
          key={"key" + j + "_" + i}
          style={{
            width: cell_size,
            height: cell_size,
            backgroundColor: "white",
          }}
        ></View>
      );
    }
    rows.push(
      <View
        key={"row" + i}
        style={{
          width: cell_size * width,
          height: cell_size,
          flexDirection: "row",
        }}
      >
        {row_elms}
      </View>
    );
  }

  return (
    <View
      style={{
        justifyContent: "center",
        alignItems: "center",
        height: "100%",
        width: "100%",
        backgroundColor: "black",
      }}
    >
      <View style={{ width: cell_size * width, height: cell_size * height }}>
        {rows}
      </View>
    </View>
  );
}

I get this outputs on android vs ios:

enter image description here

I can then for example verify that the problem occurs by using the expo build in element inspector (or alternatively with the logging method from above), that 1. the Container doesn't exactly have the correct size and also I noticed that some of the grid cells also don't have the correct size, as you can see in these to screenshots of me using the element inspector: enter image description here

Upvotes: 6

Views: 2261

Answers (2)

Re Senpai
Re Senpai

Reputation: 71

Try simply rounding your pixels to whole numbers. For example, through:

Math.round()

Or you can use the PixelRatio.roundToNearestPixel(number) method from the react-native

Read more about roundToNearestPixel here

Upvotes: 3

Artal
Artal

Reputation: 9143

These small offset that you see are due to the fact that different devices have different pixel densities. In other words, they have a different amount of pixels per square inch.

When you specify absolute values for width/height, RN will snap to the nearest pixel to avoid producing blurry visuals, which might not be exactly what you want in case you're trying to produce a perfect grid.

To avoid it, you can round the cell size to the nearest pixel. In the above example it would look like this:

import {PixelRatio} from 'react-native';    
const cell_size = PixelRatio.roundToNearestPixel(53);

You can read more about PixelRatio here.

Upvotes: 5

Related Questions