[Android] Compose Canvas

푸른하늘·2022년 8월 28일
0
post-thumbnail

Canvas 왜 사용할까?

화면에 표시되는 내용을 정확하게 제어하며 정교한 작업이 필요로 할때 사용

Jetpaco Compsoe Canvas

  • Canvas를 더욱 쉽게 사용할 수 있게 되었습니다.
  • View 를 상속받을 필요 없이 굉장히 쉬운 방법으로 UI 를 그릴 수 있습니다
  • 그래픽 요소의 상태를 최소화하므로 상태의 프로그래밍 실수를 피할 수 있습니다.
  • 항목을 그릴 때 모든 옵션이 구성 가능한 함수의 예상되는 위치에 있습니다.

📌CanVas 이해가기

View는 수백만개 의 픽셀이 하나로 모여 화면을 생성하게됩니다.

  • 그림 (0,0) ~(242,242)으로 시작해서 어떻게 픽셀이 배열되는지 볼 수 있습니다
  • 왼쪽에서 오른족 방향은 x 축을 형성하고 위에서 아래 Y축을 형성합니다.
  • 이런 요소를 사용하여 UI 배치하기 위한 기반을 형성 합니다.

drawLine

말 그대로 선을 그려 주는 함수이다

Canvas(modifier = Modifier.fillMaxSize()) {
    val canvasWidth = size.width
    val canvasHeight = size.height

    drawLine(
        start = Offset(x = canvasWidth, y = 0f),
        end = Offset(x = 0f, y = canvasHeight),
        color = Color.Blue
    )
}

drawCircle

원을 그려주는 함수이다.

Canvas(modifier = Modifier.fillMaxSize()) {
    val canvasWidth = size.width
    val canvasHeight = size.height
    drawCircle(
        color = Color.Blue,
        center = Offset(x = canvasWidth / 2, y = canvasHeight / 2),
        radius = size.minDimension / 4
    )
}

drawRect

직사각형 혹은 정사각형을 그려주는 함수이다

Canvas(modifier = Modifier.fillMaxSize()) {
        val canvasSize = size
        val canvasWidth = size.width
        val canvasHeight = size.height
        drawRect(
            color = Color.Gray,
            topLeft = Offset(x = canvasWidth / 3F, y = canvasHeight / 3F),
            size = canvasSize / 3F
        )
    }

🌳적용하기

🍎 인스타그램 로고 만들어보기

인스타그램

둥근 직사각형 + 원 + 그라데이션 으로 이루어 져있다.

  • 일정한 사이즈(정사각형)을 유지하기 위해서 size(100.dp)를 사용하였습니다.
  • 위에 그림처럼 (0,0) 부터 좌표가 시작되는 둥근 사각형입니다
  • 가운데 있는 도넛원은 (50,50) Defalut값으로 OffSet(위치) 됩니다.
  • 오른쪽 위에 있는 색칠된 원은 (80,20)에 Offset(위치) 됩니다

그리고 그레디언트가 필요하며 둥근 사각형안에 둥근 도넛원을 획 채우기로 만들어야 합니다. 코드로 한 번 보겠습니다.

drawRoundRect

  • 둥근 사각형을 그리는 경우 사용됩니다
  • Brush를 통해 그라디언트 효과를 적용 했습니다.
  • Stroke 를 사용하여 스타일을 채웠습니다

drawCirlce

  • 빈 원을 만들거나 채워진 원을 만들 수 있습니다.
  • radius를 통해 원의 크기를 설정합니다.
  • Default가 (50,50) 이기 때문에 조정할 필요한 경우만 Offset을 설정하여 위치를 옮겨 줍니다.
 val instaColors = listOf(Color.Yellow, Color.Red, Color.Magenta)
    Canvas(
        modifier = Modifier
            .size(100.dp)
            .padding(16.dp)
    ) {
        drawRoundRect(
            brush = Brush.linearGradient(colors = instaColors),
            cornerRadius = CornerRadius(60f, 60f),
            style = Stroke(width = 15f, cap = StrokeCap.Round)
        )
        drawCircle(
            brush = Brush.linearGradient(colors = instaColors),
            radius = 45f,
            style = Stroke(width = 15f, cap = StrokeCap.Round)
        )
        drawCircle(
            brush = Brush.linearGradient(colors = instaColors),
            radius = 13f,
            center = Offset(this.size.width * .80f, this.size.height * 0.20f),
        )
    }

🍎 페이스북 로고 만들어보기

페이스북

둥근 사각형 + 텍스트 사용자 글꼴 + 색상

  • Facebook Font 싸이트에서 OTF 파일을 가져와서 asset 패키지를 만들어 넣어준다.
  • Canvas에 Text를 그릴 수 있는 API가 없기 때문에 LocalText에서 가져와서 그려야 합니다.
  • paint 변수로 Size와 Color 와 typeface를 가져와서 Canvas안에 넘겨줍니다.
 val assetManager = LocalContext.current.assets
    val paint = Paint().apply {
        textAlign = Paint.Align.CENTER
        textSize = 200f
        color = Color.White.toArgb()
        typeface = Typeface.createFromAsset(assetManager, "FACEBOLF.OTF")
    }
    Canvas(
        modifier = Modifier
            .size(100.dp)
            .padding(16.dp)
    ) {
        drawRoundRect(
            color = Color(0xFF1776d1),
            cornerRadius = CornerRadius(20f, 20f)
        )
        drawContext.canvas.nativeCanvas.drawText("f", center.x + 25, center.y + 90, paint)
    }

🍎 페이스북 메신져

메신져

타원형 + 그리디언트 + Path

  • 이 메신져 모양은 말풍성 모양의 타원형이 필요합니다
  • Path를 사용하여 경로를 시작하는 위치를 설정해야 합니다
  • 그다음 주어진 좌표를 활용하여 말풍선 가장자리를 형성해야 합니다.
  • 밑부분은 음영을 주여 브러시처리를 해야줘야합니다.
val colors = listOf(Color(0xFF02b8f9), Color(0xFF0277fe))
    Canvas(
        modifier = Modifier
            .size(100.dp)
            .padding(16.dp)
    ) {

        val trianglePath = Path().let {
            it.moveTo(this.size.width * .20f, this.size.height * .77f)
            it.lineTo(this.size.width * .20f, this.size.height * 0.95f)
            it.lineTo(this.size.width * .37f, this.size.height * 0.86f)
            it.close()
            it
        }

        val electricPath = Path().let {
            it.moveTo(this.size.width * .20f, this.size.height * 0.60f)
            it.lineTo(this.size.width * .45f, this.size.height * 0.35f)
            it.lineTo(this.size.width * 0.56f, this.size.height * 0.46f)
            it.lineTo(this.size.width * 0.78f, this.size.height * 0.35f)
            it.lineTo(this.size.width * 0.54f, this.size.height * 0.60f)
            it.lineTo(this.size.width * 0.43f, this.size.height * 0.45f)
            it.close()
            it
        }

        drawOval(
            Brush.verticalGradient(colors = colors),
            size = Size(this.size.width, this.size.height * 0.95f)
        )

        drawPath(
            path = trianglePath,
            Brush.verticalGradient(colors = colors),
            style = Stroke(width = 15f, cap = StrokeCap.Round)
        )

        drawPath(path = electricPath, color = Color.White)

    }

🍎 토스 만들어보기

토스

타원형 + 그리디언트 + Path 위에 메신저랑 형태가 흡사하다

(추가 작업중)

profile
Developer-Android-CK

0개의 댓글