compose 화면 dp

1

AndroidStudio

목록 보기
56/83
post-custom-banner

https://medium.com/proandroiddev/supporting-different-screen-sizes-on-android-with-jetpack-compose-f215c13081bd

  • 안드로이드의 레이아웃이나 UI 요소를 생성하기 위해 픽셀 대신 dp를 사용하는것이 좋은이유는 분명합니다.
    dp는 여러가지 화면에서 서로 다른 densities에서도 최대한 동일한 화면을 보여주기 위해 고려된 방법입니다.
    DP는 기본적으로 160dpi스크린의 1px을 기준으로 잡은 가상의 픽셀이라고 생각하면 됩니다.
    즉, 50dp를 생각했을때 갤럭시 S22이든 Nexus One모델이든 상관없이 동등한 px값을 변환해서 부여해주는것입니다.

문제점

Here’s the same screen using the same dimensions on Nexus One (left) and Pixel 5 (right)

  • 문제는 동등한 dpi를 사용하는 다른 모바일 기기의 경우 발생합니다.
    dpi는 동일하지만 물리적인 핸드폰의 크기가 다르기 때문에 padding, margin이 모두 다르게 적용이 되며 좌측과 같이 화면이 잘리는 경우가 종종 발생하게 됩니다.
    이를 위해 match_parent를 사용하거다 ratio를 이용한 비율로 화면을 구성하는 방법이 있지만 이것은 절대적인 것이 아니며 임시방편일 뿐입니다.

  • 사용할 dimensions정리

class Dimensions(
    val grid_0_25: Dp,
    val grid_0_5: Dp,
    val grid_1: Dp,
    val grid_1_5: Dp,
    val grid_2: Dp,
    val grid_2_5: Dp,
    val grid_3: Dp,
    val grid_3_5: Dp,
    val grid_4: Dp,
    val grid_4_5: Dp,
    val grid_5: Dp,
    val grid_5_5: Dp,
    val grid_6: Dp,
    val plane_0: Dp,
    val plane_1: Dp,
    val plane_2: Dp,
    val plane_3: Dp,
    val plane_4: Dp,
    val plane_5: Dp,
    val minimum_touch_target: Dp = 48.dp,
)

val smallDimensions = Dimensions(
    grid_0_25 = 1.5f.dp,
    grid_0_5 = 3.dp,
    grid_1 = 6.dp,
    grid_1_5 = 9.dp,
    grid_2 = 12.dp,
    grid_2_5 = 15.dp,
    grid_3 = 18.dp,
    grid_3_5 = 21.dp,
    grid_4 = 24.dp,
    grid_4_5 = 27.dp,
    grid_5 = 30.dp,
    grid_5_5 = 33.dp,
    grid_6 = 36.dp,
    plane_0 = 0.dp,
    plane_1 = 1.dp,
    plane_2 = 2.dp,
    plane_3 = 3.dp,
    plane_4 = 6.dp,
    plane_5 = 12.dp,
)

val sw360Dimensions = Dimensions(
    grid_0_25 = 2.dp,
    grid_0_5 = 4.dp,
    grid_1 = 8.dp,
    grid_1_5 = 12.dp,
    grid_2 = 16.dp,
    grid_2_5 = 20.dp,
    grid_3 = 24.dp,
    grid_3_5 = 28.dp,
    grid_4 = 32.dp,
    grid_4_5 = 36.dp,
    grid_5 = 40.dp,
    grid_5_5 = 44.dp,
    grid_6 = 48.dp,
    plane_0 = 0.dp,
    plane_1 = 1.dp,
    plane_2 = 2.dp,
    plane_3 = 4.dp,
    plane_4 = 8.dp,
    plane_5 = 16.dp,
)
  • 기본 dimensions를 지정하고 특정 상황에 맞는 dimension을 지정합니다.
  • 테마에 Dimens를 지정합니다.
    디바이스의 screenDp는 configuration을 통하여 구할수 있습니다.
@Composable
fun ProvideDimens(
    dimensions: Dimensions,
    content: @Composable () -> Unit
) {
    val dimensionSet = remember { dimensions }
    CompositionLocalProvider(LocalAppDimens provides dimensionSet, content = content)
}

private val LocalAppDimens = staticCompositionLocalOf {
    smallDimensions
}

@Composable
fun AppTheme(
    darkTheme: Boolean = isSystemInDarkTheme(),
    content: @Composable () -> Unit
) {
    val colors = if (darkTheme) DarkThemeColors else LightThemeColors
    val configuration = LocalConfiguration.current
    val dimensions = if (configuration.screenWidthDp <= 360) smallDimensions else sw360Dimensions
    val typography = if (configuration.screenWidthDp <= 360) smallTypography else sw360Typography

    ProvideDimens(dimensions = dimensions) {
        ProvideColors(colors = colors) {
            MaterialTheme(
                colors = colors,
                shapes = Shapes,
                typography = typography,
                content = content,
            )
        }
    }
}

object AppTheme {
    val colors: Colors
        @Composable
        get() = LocalAppColors.current

    val dimens: Dimensions
        @Composable
        get() = LocalAppDimens.current
}

val Dimens: Dimensions
    @Composable
    get() = AppTheme.dimens

Row(
  modifier = Modifier.padding(
    horizontal = AppTheme.dimens.grid_2,
    vertical = AppTheme.dimens.grid_3
  ),
) {
  ...
}
profile
러닝커브를 따라서 등반중입니다.
post-custom-banner

0개의 댓글