RIEN😚
이상한 나라의 개발자
RIEN😚
전체 방문자
오늘
어제
  • 분류 전체보기 (125)
    • Algorithm (68)
      • 알고리즘 (0)
      • Baekjoon (8)
      • 프로그래머스 (55)
      • HackerRank (5)
    • Android (30)
      • Project (1)
      • Error (2)
      • Studio (1)
      • Android (26)
    • Kotlin (6)
    • CS (4)
      • 네트워크 (2)
      • 데이터베이스 (2)
    • Front End (5)
      • React (1)
      • VUE (3)
      • Project (0)
      • 기타 (1)
    • 기록 (11)
      • 회고록 (6)
      • TIL (5)

블로그 메뉴

  • Github🔥
  • 포트폴리오🌹

공지사항

인기 글

티스토리

250x250
반응형
hELLO · Designed By 정상우.
RIEN😚

이상한 나라의 개발자

Android/Android

[Compose] Custom BoxShadow를 만들어보자!

2023. 4. 4. 19:43
728x90
반응형

토이 프로젝트를 진행하던 중....

👇🏻 요런 느낌의 BoxShadow를 원했지만

 

Surface의 elevation으로만으로는 만족스러운 결과물을 만들수 없었습니다. 😭

하지만 UI에는 진심인 개발자로서 Custom BoxShadow를 만드는 방법에 대해서 찾아보았습니다. 🔥🔥

 

결과적으로는 👇🏻아래와 같이 기획이라는 쪼~금 다르지만 만족스러운 Preview를 만들 수 있었습니다. 👍🏻

 

코드를 잠깐 확인해보면

fun Modifier.shadow(
    color: Color, // 그림자 색상
    elevation: Dp = 0.dp, // 그림자 offset
    spread: Float = 30f // 그림자 퍼짐(?) 정도
) = this.drawBehind { /* */ }

Modifier로 쉽게 적용할 수 있도록 Modifier의 확장함수로 만들어 사용하고 있습니다.

 

1. drawBehind

Modifier가 적용되는 content 뒤!에 draw 작업을 하는 Modifier입니다.

주어지는 이미지, 정확히는 이미지를 포함하는 Surface 뒤에 Shadow를 그려줄 예정이므로 drawBehind가 필요합니다. 🤗

 

2. drawIntoCanvas

적당한 Shadow를 화면에 직접 그리기 위해 Canvas를 준비해줍니다.

this.drawIntoCanvas { /* */ }
그림자 그리기! 🪴
this.drawIntoCanvas {
    val paint = Paint()
    val frameworkPaint = paint.asFrameworkPaint()
    frameworkPaint.color = transparentColor
    // 그림자 크기와 위치 설정
    frameworkPaint.setShadowLayer(
        spread,
        elevation.toPx(),
        elevation.toPx(),
        shadowColor
    )
    // 실제 그리는 부분
    it.drawRect(
        0f,
        0f,
        this.size.width,
        this.size.height,
        paint
    )
}

 

3. 전체 코드

더보기
fun Modifier.shadow(
    color: Color, // 그림자 색상
    elevation: Dp = 0.dp, // 그림자 offset
    spread: Float = 30f // 그림자 퍼짐(?) 정도
) = this.drawBehind {
    val transparentColor = android.graphics.Color.toArgb(color.copy(alpha = 0.0f).value.toLong())
    val shadowColor = android.graphics.Color.toArgb(color.copy(alpha = 1f).value.toLong())
    this.drawIntoCanvas {
        val paint = Paint()
        val frameworkPaint = paint.asFrameworkPaint()
        frameworkPaint.color = transparentColor
        // 그림자 크기와 위치 설정
        frameworkPaint.setShadowLayer(
            spread,
            elevation.toPx(),
            elevation.toPx(),
            shadowColor
        )
        // 실제 그리는 부분
        it.drawRect(
            0f,
            0f,
            this.size.width,
            this.size.height,
            paint
        )
    }
}

 

4. 사용해보기

저는 Surface를 커스텀하게 사용하기 위해 별도의 Component로 만들어 사용하고 있습니다. 🤗

이렇게 만들어둔 Component를 Preview에서 호출해보겠습니다. 🔥👍🏻

@Preview(name = "Surface")
@Composable
fun SurfacePreview() {
    AllForMemoryTheme {
        Box(
            modifier = Modifier
                .fillMaxSize()
                .background(Brush.linearGradient(HarooTheme.colors.interactiveBackground))
        ) {
            HarooSurface(
                modifier = Modifier.padding(10.dp).size(120.dp),
                elevation = 10.dp
            ) {
                Box(
                    modifier = Modifier
                        .fillMaxSize()
                        .background(HarooTheme.colors.uiBackground)
                )
            }
        }
    }
}

만족스러운 Shadow를 가지는 Surface가 되었습니다. 👏🏻👏🏻👏🏻👏🏻

 

반응형

'Android > Android' 카테고리의 다른 글

[Android] 실행시점에 Permission 요청하기  (0) 2023.04.23
[Android] 2023 Google Play Policy Bytes  (0) 2023.04.12
[Compose] Font에 적용되는 Padding 제거하기  (0) 2023.04.04
[Android] Room을 이용해 만든 Database와 dao는 어떻게 생겼을까?  (0) 2023.04.01
[Android/Compose] 언제 Recomposition이 발생하는 것일까?  (0) 2023.03.26
    'Android/Android' 카테고리의 다른 글
    • [Android] 실행시점에 Permission 요청하기
    • [Android] 2023 Google Play Policy Bytes
    • [Compose] Font에 적용되는 Padding 제거하기
    • [Android] Room을 이용해 만든 Database와 dao는 어떻게 생겼을까?
    RIEN😚
    RIEN😚
    안드로이드 / 코틀린 독학으로 취업하자!

    티스토리툴바