androidandroid-jetpack-composeandroid-tv

Why dp doesn't work for android TV as expected?


I work on the screen for android TV (Jetpack Compose) implementation where (specifically) Card size looks differently for (emulator) 720p TV and 1080p TV

720: enter image description here

1080: enter image description here

Card code:

...
Card(
            modifier = Modifier
                .width(412.dp)
                .height(200.dp),
            border = CardDefaults.border(border = Border.None),
            colors = CardDefaults.colors(
                containerColor = ColorTokens.grey_40,
                contentColor = ColorTokens.white,
                focusedContainerColor = Color.White,
                focusedContentColor = Color.Black,
                pressedContainerColor = Color.Gray,
                pressedContentColor = Color.LightGray
            ),
            shape = CardDefaults.shape (shape = RoundedCornerShape(CornerRadiusTokens.radius_300.withDPIOffset(LocalContext.current))),
            onClick = { /*TODO*/ },
        )
...

I would expect Cards to looks the same for both screens since dp in use, what am I missing here?


Solution

  • Finally, I got an idea, the problem is that our design was done for the screen 1080p with all the UI items values in px (not dp). It means that once you try to use let's say 200px for different screens obviously it would look different.

    So, in order to support screens 1080p as well as 720p it is necessary to adjust sizes from 1080 to 720 screens

    There is a function:

    inline val Int.extToDp: Dp
        @Composable get() = with(LocalDensity.current) { this@extToDp.toDp() }
    
    val Int.pxToDpWithOffset: Dp
        @Composable get() {
            val screenDensity: Float = LocalContext.current.resources.displayMetrics.densityDpi.toFloat()
    
            val factor: Float = when {
                screenDensity <= DisplayMetrics.DENSITY_TV -> {
                    (screenDensity / DisplayMetrics.DENSITY_XHIGH)
                }
    
                else /* DisplayMetrics.DENSITY_XHIGH */ -> {
                    1f
                }
            }
    
            val adjustedDp: Int = (this * factor).roundToInt()
            return adjustedDp.extToDp
        }
    

    Usage:

    ...
                modifier = Modifier
                    .width(412.pxToDpWithOffset)
                    .height(200.pxToDpWithOffset)
    ...
    

    P.S.: Let me know if you see any ways for improvements