728x90
개요
- 안드로이드에서 룰렛을 Custom View를 통해 직접 그리고 회전시켜보는 예제 코드입니다.
- 코드는 코틀린으로 작성했습니다.
- 작업된 코드는 아래 github 주소를 확인해주세요.
- 작성일 기준 아직 미완성입니다 ㅜㅜ
- 가이드 코드와 약간 다릅니다.
- github.com/JhDroid/android-roulette-wheel-view
룰렛 그리기
1. 커스텀 뷰 클래스 생성
package com.jhdroid.roulette
import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.View
class Roulette @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
}
2. 룰렛 배경 그리기
- 룰렛의 원을 그리기 전에 룰렛을 그리는 방법을 설명해드리겠습니다.
- 룰렛 배경과 룰렛의 내부 판(?)은 한 번에 그릴 수 없어서 나눠서 그려야 합니다.
- 위 이미지처럼 룰렛을 그리려면 먼저 배경 원을 그리고 내부 원을 그려줘야 합니다.
- 먼저 룰렛의 배경을 그려보겠습니다.
- 룰렛의 배경은 바로 그리지 않고 먼저 정사각형을 만들고 그 정사각형 안에 그리는 방식으로 그려야 합니다.
- 이 정사각형을 통해 내부 원도 그려야 합니다.
class Roulette @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
private val strokePaint = Paint()
private val rectF = RectF()
init {
strokePaint.apply {
color = Color.BLACK
style = Paint.Style.STROKE
strokeWidth = 15f
isAntiAlias = true
}
}
@SuppressLint("DrawAllocation")
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
val rectLeft = left.toFloat() + paddingLeft
val rectRight = right - paddingRight
val rectTop = height / 2f - rectRight / 2f + paddingTop
val rectBottom = height / 2f + rectRight / 2f - paddingRight
rectF.set(rectLeft, rectTop, rectRight, rectBottom)
canvas?.drawArc(rectF, 0f, 360f, true, strokePaint)
}
}
- 코드 설명
- strokePaint
- style : 스타일을 Paint.Style.STOKE를 설정해주지 않으면 원의 내부가 채워진 원으로 그려집니다.
- isAntiAlias : Paint 설정 시 AntiAlias 설정해주면 부드럽게 원을 그려줍니다.
- rectF
- left, right, top, bottom : 정사각형의 크기를 설정합니다. 룰렛을 뷰의 중앙에 그려주기 위해 top은 뷰의 중앙에서 가로의 반만큼 위로, bottom은 중앙에서 가로의 반만큼 아래로 설정해줍니다.
- rectRight == width
- left, right, top, bottom : 정사각형의 크기를 설정합니다. 룰렛을 뷰의 중앙에 그려주기 위해 top은 뷰의 중앙에서 가로의 반만큼 위로, bottom은 중앙에서 가로의 반만큼 아래로 설정해줍니다.
- drawArc(RectF, 시작 각도, 회전 각도, 중앙 사용 여부, Paint())
- 원을 그릴 떼는 시작 각도에서 회전 각도만큼 시계 방향으로 그립니다.
- 시작 각도를 0도로 설정하면 오른쪽 중앙에서부터 시계 방향으로 원을 그립니다.
- 배경 원은 중앙 사용 여부가 중요하지 않습니다. (true나 false 아무거나 설정하면 됩니다.)
- strokePaint
- 위 과정까지 완료하면 뷰 중앙에 원을 그릴 수 있습니다.
- 안드로이드 스튜디오 최신 버전을 사용하고 있다면 스튜디오 오른쪽에서 빌드하면서 draw 되는 과정을 확인할 수 있습니다.
3. 룰렛 내부 그리기
- 룰렛 내부는 룰렛의 사이즈(2~8)에 따라서 다르게 그려줘야 합니다.
- 룰렛 내부는 룰렛 배경처럼 drawArc() 함수를 통해 룰렛 사이즈에 맞게 원을 여러 개 그려야 합니다.
class Roulette @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
private val rectF = RectF()
private val strokePaint = Paint()
private val fillPaint = Paint()
private var rouletteSize = 2
init {
strokePaint.apply {
color = Color.BLACK
style = Paint.Style.STROKE
strokeWidth = 15f
isAntiAlias = true
}
fillPaint.apply {
style = Paint.Style.FILL
isAntiAlias = true
}
}
@SuppressLint("DrawAllocation")
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
val rectLeft = left.toFloat() + paddingLeft
val rectRight = right - paddingRight
val rectTop = height / 2f - rectRight / 2f + paddingTop
val rectBottom = height / 2f + rectRight / 2f - paddingRight
rectF.set(rectLeft, rectTop, rectRight, rectBottom)
drawRoulette(canvas, rectF)
}
private fun drawRoulette(canvas: Canvas?, rectF: RectF) {
canvas?.drawArc(rectF, 0f, 360f, true, strokePaint)
if (rouletteSize in 2..8) {
val sweepAngle = 360f / rouletteSize.toFloat()
val colors = listOf("#fe4a49", "#2ab7ca", "#fed766", "#e6e6ea", "#f6abb6", "#005b96", "#7bc043", "#f37735")
for (i in 0 until rouletteSize) {
fillPaint.color = Color.parseColor(colors[i])
val startAngle = if (i == 0) 0f else sweepAngle * i
canvas?.drawArc(rectF, startAngle, sweepAngle, true, fillPaint)
}
} else throw RuntimeException("size out of roulette")
}
}
- 코드 설명
- fillPaint
- style : 스타일을 Paint.Style.FILL 설정을 해주지 않아도 되지만 명시적으로 추가했습니다.
- rouletteSize
- 룰렛의 크기를 결정합니다. 이 변수는 나중에 사용자에게 입력받습니다.
- 룰렛이 다르게 그려지는 것을 확인하고 싶으면 이 변수의 값을 변경하면 됩니다.
- 룰렛은 최소 2에서 최대 8까지의 수입니다.
- drawRoulette(Canvas, RectF)
- 룰렛을 그려주는 함수입니다. 기존에 배경을 그리는 코드를 이 함수로 옮겼습니다.
- sweepAngle
- 룰렛의 회전 각도를 담는 변수입니다.
- 회전 각도는 룰렛 크기에 따라 달라지므로 '360 / 룰렛 사이즈'를 통해 구할 수 있습니다.
- fillPaint.color
- 순서대로 색상을 변경하기 위한 코드입니다.
- startAngle
- 시작 각도를 담는 변수입니다.
- 시작 각도는 최초에는 0에서 시작해서 회전 각도만큼 커집니다.
- 룰렛 사이즈가 4일 때 회전 각도는 90
- 1 - 0 ~ 90
- 2 - 90 ~ 180
- 3 - 180 ~ 270
- 4 - 270 ~ 360
- 단 여기서 회전 각도는 90으로 변하면 안 됩니다.
- 룰렛 사이즈가 4일 때 회전 각도는 90
- drawArc()
- 내부 원은 중앙 사용을 허용하고 그려줘야 합니다.
- fillPaint
- 이 비교 이미지만 보면 중앙 사용이 무슨 소리인지 이해가 될 거라고 생각됩니다.
- 여기까지 완료했다면 룰렛판 그리기는 끝났습니다.
다음 글은 룰렛 내부에 텍스트를 표시하고 회전 애니메이션을 추가하는 방법입니다.
* 글에 틀린 부분이 있으면 댓글 부탁드립니다 :)
728x90
'프로젝트 > Roulette Wheel View' 카테고리의 다른 글
[Roulette] 룰렛을 그리고 회전시키기 (4) - 사용 편의성 개선 (0) | 2021.03.13 |
---|---|
[Roulette] 룰렛을 그리고 회전시키기 (3) - 회전 결과 리턴하기 (0) | 2021.03.01 |
[Roulette] 룰렛을 그리고 회전시키기 (2) - 텍스트 쓰기, 애니메이션 적용 (0) | 2021.02.23 |