I simply want to offset an Image always the exact amount no matter what screen resolution the user has.
I tried it like this:
var heightIs by remember { mutableStateOf(0f) }
Box(
modifier = Modifier
.fillMaxSize()
.aspectRatio(
ratio = 1f
).onGloballyPositioned { coordinates ->
heightIs = (coordinates.size.height.toFloat())
}
) {
Image(
painter = painterResource(id = R.drawable.base),
contentDescription = "Shadow",
modifier = Modifier.fillMaxSize()
)
Image(
painter = painterResource(id = R.drawable.top_mask_normal),
contentDescription = "Shadow Stencil",
colorFilter = ColorFilter.tint(color, BlendMode.SrcAtop),
modifier = Modifier
.fillMaxSize()
.offset(y = ((heightIs * 0.03).toInt()).dp)
)
}
But I get different results on different screen resolutions. I want it exactly at the same position every time not matter if the user uses a tablet or a 480x800 device
CodePudding user response:
With this line, heightIs * 0.03).toInt()).dp
, you are not converting to dp or density independent pixels. You are adding .dp extension to end of pixel value.
To convert to dp you need to use LocalDensity.current.run{heightIs * 0.03).toInt().toDp()}
dp is calculated as pixels / density. If your device has 2.0 density 100px should be 50.dp but with your existing function you simply change 100px
to 100.dp
CodePudding user response:
.dp
just returns a Dp
type object. You want to ensure the Composable moves by a fixed 'distance', no matter the density of the screen, but pixels are of variable sizes. You'll need some sort of conversion mechanism that converts your pixel value to the something that equals the same distance on their device as it did on your device with a different density. Hence, you need the set the value (in pixels, say) on your device based on your preferred distance; then you need to convert that value on your device to a Dp
value. Then, the value you get from the conversion can be used everywhere else, on any device and it will return the same 'length', in principle.
Let's say you want a Dp
, that is, Density-Independent Pixel value for 500 pixels on your device. The conversion process is
{ // ComposableScope
val dips = with(LocalDensity.current) { pixels.toDp() }
}
Now, this value is just to get the converted pixel value to DPs. Log this value, or get it through the debugger or print it on screen or use whicvever method you want to retrieve this value. Once the value is in your hands, you no longer need this code. Just initialise the dips
variable with the retrieved value and it will work well on every device (in principle).
Also take a took at Doctor Thracian's answer.