Почему dp не работает на Android TV должным образом?

Я работаю над реализацией экрана для Android TV (Jetpack Compose), где (в частности) размер карты выглядит по-разному для (эмулятора) телевизора 720p и телевизора 1080p.

720:

1080:

Код карты:

...
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. Чего мне здесь не хватает?

Каковы размеры эмулируемого экрана ваших двух изображений эмулятора? Я предполагаю, что вы обнаружите, что экран 1080p больше.

CommonsWare 07.06.2024 19:12

@CommonsWare добавил ответ

Sirop4ik 10.06.2024 15:13

@CommonsWare о, я понял, что вы имеете в виду, извините за путаницу. Похоже, размер телевизора эмулятора по умолчанию составляет 55". Однако в моем случае проблема заключалась в том (как я описал в своем ответе), что наш дизайн (в Figma) создан только для отображения 1080p, а размеры там в пикселях. Итак, если скажем Элемент пользовательского интерфейса (в дизайне) занимает 200 пикселей, я просто использовал это значение, как в dp, например - 200.dp, но использовать значение пикселя, как в dp, неправильно. Итак, я предлагаю решение (описанное ниже в ответе). ). Имеет ли это смысл?

Sirop4ik 11.06.2024 14:11

@Sirop4ik: Лично я не до конца понимаю ваш ответ, но у меня была ошибка в предыдущем комментарии, который я сейчас удалил.

CommonsWare 11.06.2024 14:26

@CommonsWare в своем комментарии выше я имел в виду, что 200px != 200.dp

Sirop4ik 11.06.2024 14:32
2
5
54
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

Итак, для поддержки экранов 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)
...

P.S.: Дайте мне знать, если вы видите какие-либо способы улучшения.

Другие вопросы по теме