Skip to content

HomeMapButton_커스텀_UI_구현

yujin45 edited this page Nov 12, 2024 · 1 revision

✅ 진행한 기능

✅ HomeMapButton 커스텀 UI 구현

💡코드의 각 구성 요소 정리

1. Path의 크기 조정 함수

private fun Path.scale(scaleX: Float, scaleY: Float) {
    val matrix = Matrix().apply {
        reset()
        scale(scaleX, scaleY)
    }
    transform(matrix)
}

이 함수는 Path 객체의 크기를 주어진 scaleXscaleY 비율로 조정한다. Matrix를 사용하여 변환 행렬을 생성하고, 이를 통해 Path의 크기를 변환한다. 이러한 변환은 Android의 그래픽 시스템에서 일반적으로 사용되는 방식이다.

2. 커스텀 Shape 클래스 정의

class CustomShape(private val path: Path) : Shape {
    override fun createOutline(
        size: Size,
        layoutDirection: LayoutDirection,
        density: Density
    ): Outline {
        val scaleX = size.width / 373f
        val scaleY = size.height / 225f
        val scale = minOf(scaleX, scaleY)

        val scaledPath = Path().apply {
            addPath(path)
            scale(scale, scale)
        }
        return Outline.Generic(scaledPath)
    }
}

CustomShape 클래스는 Shape 인터페이스를 구현하여 커스텀 도형을 정의한다. createOutline 메서드에서 주어진 Path를 컨테이너의 크기에 맞게 스케일링하여 Outline을 생성한다. 이러한 커스텀 Shape를 정의하는 방법은 Jetpack Compose의 공식 문서에서 다루고 있다.

minOf(scaleX, scaleY) 가장 작은 비율을 기준으로 사용하는 이유

  • 주어진 PathShape으로 정의하는 CustomShape 클래스에서, createOutline 메서드는 주어진 크기에 맞게 Path를 스케일링하여 Outline을 생성한다. 이때, scaleXscaleY 중 작은 값을 선택하여 양쪽에 동일한 스케일을 적용하는 이유는 원본 Path의 종횡비를 유지하기 위함이다.
  • 만약 scaleXscaleY 중 큰 값을 선택하여 스케일링을 적용하면, 원본 Path의 종횡비가 왜곡되어 의도한 모양과 다르게 렌더링될 수 있다. 따라서 작은 값을 기준으로 스케일링을 적용함으로써 원본의 비율을 유지하며, 주어진 크기에 맞게 조정할 수 있다.
  • 이러한 접근 방식은 그래픽 처리에서 일반적으로 사용되며, Jetpack Compose의 공식 문서에서도 유사한 내용이 언급되고 있다.
  • https://developer.android.com/develop/ui/compose/graphics/draw/overview?hl=ko

3. HomeMapButton 컴포저블 함수

@Composable
fun HomeMapButton(
    modifier: Modifier = Modifier,
    text: String,
    textColor: Color,
    onClick: () -> Unit
) {
    val pathData = "M341.33,88.24C356.06,80.33 366.08,64.79 366.08,46.9C366.08,21 345.08,0 319.18,0C303.29,0 289.24,7.91 280.76,20H10C4.48,20 0,24.48 0,30V197C0,202.52 4.48,207 10,207H210.59L204.45,218.71H216.76L213.81,224.33H356.96L373,91.36L362.82,92.5L363.64,85.74L341.33,88.24Z"
    val path = PathParser().parsePathString(pathData).toPath()

    Box(
        modifier = modifier
            .fillMaxWidth()
            .aspectRatio(373f / 225f)
            .clip(CustomShape(path))
            .clickable { onClick() }
    ) {
        Image(
            painter = painterResource(id = R.drawable.btn_home_menu_map_background),
            contentDescription = null,
            contentScale = ContentScale.Crop,
            modifier = Modifier.fillMaxSize()
        )

        Text(
            text = text,
            modifier = Modifier
                .padding(start = 16.dp, top = 36.dp),
            color = textColor
        )
    }
}
  • 이 컴포저블 함수는 커스텀 모양의 버튼을 생성한다. PathParser를 사용하여 pathData 문자열을 Path 객체로 변환하고, 이를 CustomShape로 감싸서 clip에 적용한다. Box 내부에는 ImageText를 배치하여 버튼의 내용을 구성한다.

참고 링크

https://developer.android.com/develop/ui/compose/graphics/draw/shapes

https://developer.android.com/develop/ui/compose/graphics/draw/modifiers

https://developer.android.com/develop/ui/compose/graphics/images/customize

https://developer.android.com/develop/ui/compose/custom-modifiers

https://developer.android.com/reference/kotlin/androidx/compose/ui/graphics/package-summary (PathParser)

https://developer.android.com/develop/ui/compose/graphics/images/customize?hl=ko

https://developer.android.com/develop/ui/views/graphics/vector-drawable-resources?hl=ko

Clone this wiki locally