Reputation: 901
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:
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:
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:
Upvotes: 6
Views: 2261
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
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