Reputation: 40662
Most of Jetpack Compose API uses Dp as a dimensions unit, but sometimes a pixel value is required. How can I convert a dp value to px? Just for an example there's graphicsLayer() modifier that accepts translationX/Y
arguments in pixels.
Upvotes: 90
Views: 78326
Reputation: 13
With some little tweaks to @Oliver Metz's solution -
@Stable fun Dp.toPx(): Float = this.value * Resources.getSystem().displayMetrics.density
this is a clean way to convert dp to px without needing the function to be a composable, which makes it a little performant and even allows it to be used outside composables.
also, @Sirop4ik's solution has no benefits, 1. Inlining these converters means the same code is gonna be copied to the call site, increasing app size. This is especially noticeable if u use it a lot. 2. Using a getter instead of a function, this makes the usage like this - 120.dp.toPx as opposed to 120.dp.toPx(). Which doesn't look the way how we use the converters like .toInt(), .toString() etc. More importantly these getters are anyway compiled to functions. for example,
val testVariable: Int get() = 1
fun testFunction(): Int = 1
Is compiled to-
public static final int getTestVariable() { return 1; }
public static final int testFunction() { return 1 }
So, this has no difference.
Upvotes: 1
Reputation: 5263
I use this approach and there are two advantages:
inline val Int.dp: Dp
@Composable get() = with(LocalDensity.current) { [email protected]() }
inline val Dp.px: Float
@Composable get() = with(LocalDensity.current) { [email protected]() }
Upvotes: 4
Reputation: 3798
@Valeriy's answer is definitely the correct way to do it but if you want it slightly less verbose or you have a lot of converting to do you can create extension functions:
@Composable
fun Dp.dpToPx() = with(LocalDensity.current) { [email protected]() }
@Composable
fun Int.pxToDp() = with(LocalDensity.current) { [email protected]() }
This lets you convert your dp straight to px and vice versa.
val dpValue = 16.dp
val pxConverted = dpValue.dpToPx()
val pxValue = 100
val dpConverted = pxValue.pxToDp()
Upvotes: 54
Reputation: 40662
There're toPx()
and roundToPx()
methods defined by Density interface, you can use it like this:
import androidx.compose.ui.platform.LocalDensity
val pxValue = with(LocalDensity.current) { 16.dp.toPx() }
// or
val pxValue = LocalDensity.current.run { 16.dp.toPx() }
Such an expression might look confusing if you're new to Kotlin language so let's break it down and see how it works. toPx()
is an extension function of Dp
class, you can think of it as a Dp
class method. But since toPx()
is defined inside Density interface, you cannot use it unless you provide a density as a receiver. And at last you can get the current density from an CompositionLocal named LocalDensity.
Upvotes: 210