On my Pixel 7 device, I want to know how many density-independent pixels (dp) I have. So, I use this formula:
displayMetrics.widthPixels / displayMetrics.density
However, I have an issue because displayMetrics.widthPixels = 1080
(which is okay) and displayMetrics.density = 2.625
. When I calculate 1080 / 2.625, it equals 411.428571 density-independent pixels, which is not an integer. It seems that displayMetrics.density = 2.625 may be incorrect because it's unusual to have a fraction of a density-independent pixel.
How can I obtain the correct value for displayMetrics.density? I suppose it's 2.62135922, which would result in 412 density-independent pixels, making it seem more visually appealing.
Looking at the Android's official dp-px conversion formula, one can say your calculation as such is correct. And displayMetrics.density
is not wrong. The thing is, that
One dp is a virtual pixel unit that's roughly equal to one pixel on a medium-density screen (160 dpi, or the "baseline" density). Android translates this value to the appropriate number of real pixels for each other density.
This definiton of one dp
is platform-dependent, e.g. Windows has another one. So your formula is indeed
px = dp * (dpi / 160)
<=> px = dp * displayMetrics.density
<=> dp = px / displayMetrics.density
<=> dp = displayMetrics.widthPixels / displayMetrics.density
as density is defined as dpi/160
.
However, as the holy docs say
Never hardcode this equation
and one should use applyDimension()
for the conversion from dp
to px
. Analogously, deriveDimension()
converts px
to dp
.
Now you say: "Wait a moment, deriveDimension()
only comes with Android 14. What shall I do in the meantime?"
Note, that applyDimension()
and deriveDimension()
both return float
values. The docs' example for applyDimension()
applies a type conversion to Integer on the result.
So -- keep using your formula for now and simply add a type conversion of the result to Integer.