Почему dp не работает на andorid TV так как ожидается?

В Android TV я с использую Jetpack Compose, где размер Card выглядит по-разному на телевизорах с разрешением 720p (эмулятор) и 1080p (эмулятор).

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*/ },
        )
...

Я ожидал бы, что карточки будут выглядеть одинаково на обоих экранах, так как используется dp. Что я упускаю из виду?


Ответы (1 шт):

Автор решения: Sirop4ik

Проблема в том, что наш дизайн был сделан для экрана с разрешением 1080p, и все значения элементов интерфейса указаны в пикселях (px), а не в dp. Это значит, что если попытаться использовать, скажем, 200px на разных экранах, то, очевидно, будет выглядеть по-разному.

Поэтому, чтобы поддерживать экраны 1080p и 720p, необходимо корректировать размеры с 1080 до 720 экранов.

Вот функция:

inline val Int.extToDp: Dp
    @Composable get() = with(LocalDensity.current) { [email protected]() }

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
    }

Использование:

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

Дайте знать если, что то пропустил:)

→ Ссылка