
이미지처럼 배경 없는 체크 박스를 만들고 싶었다. compose material3에서 제공하는 체크박스를 사용하려고 했다.
아래처럼 해보았을 때 될 것이라고 확신했는데,, 안되더라..
@Composable
fun TransparentCheonghaCheckbox(
modifier: Modifier = Modifier,
checked: Boolean,
onCheckedChanged: (Boolean) -> Unit,
) {
Checkbox(
modifier = modifier,
colors = CheckboxDefaults.colors(
checkedColor = Color.Transparent,
uncheckedColor = Color.Transparent,
).copy(
uncheckedCheckmarkColor = WithpeaceTheme.colors.SystemGray2,
checkedCheckmarkColor = WithpeaceTheme.colors.MainPurple,
uncheckedBoxColor = Color.Unspecified,
),
checked = checked,
onCheckedChange = onCheckedChanged,
)
}
이유를 찾아보자..
가장 내부에 있는 코드이다. 아래 코드에 체크 색을 설정하고, Canvas를 통해 체크 모양을 그리는 방식이었다
/**
* Represents the color used for the checkmark inside the checkbox, depending on [state].
*
* @param state the [ToggleableState] of the checkbox
*/
@Composable
internal fun checkmarkColor(state: ToggleableState): State<Color> {
val target = if (state == ToggleableState.Off) {
uncheckedCheckmarkColor
} else {
checkedCheckmarkColor
}
val duration = if (state == ToggleableState.Off) BoxOutDuration else BoxInDuration
return animateColorAsState(target, tween(durationMillis = duration))
}
디버깅을 했을 때 색상은 문제 없이 전달되었고, Toggleablestate 또한 문제없이 전달되었다.
Canvas 코드를 보자
private fun DrawScope.drawCheck(
checkColor: Color,
checkFraction: Float,
crossCenterGravitation: Float,
strokeWidthPx: Float,
drawingCache: CheckDrawingCache
) {
val stroke = Stroke(width = strokeWidthPx, cap = StrokeCap.Square)
val width = size.width
val checkCrossX = 0.4f
val checkCrossY = 0.7f
val leftX = 0.2f
val leftY = 0.5f
val rightX = 0.8f
val rightY = 0.3f
val gravitatedCrossX = lerp(checkCrossX, 0.5f, crossCenterGravitation)
val gravitatedCrossY = lerp(checkCrossY, 0.5f, crossCenterGravitation)
// gravitate only Y for end to achieve center line
val gravitatedLeftY = lerp(leftY, 0.5f, crossCenterGravitation)
val gravitatedRightY = lerp(rightY, 0.5f, crossCenterGravitation)
with(drawingCache) {
checkPath.reset()
checkPath.moveTo(width * leftX, width * gravitatedLeftY)
checkPath.lineTo(width * gravitatedCrossX, width * gravitatedCrossY)
checkPath.lineTo(width * rightX, width * gravitatedRightY)
// TODO: replace with proper declarative non-android alternative when ready (b/158188351)
pathMeasure.setPath(checkPath, false)
pathToDraw.reset()
pathMeasure.getSegment(
0f, pathMeasure.length * checkFraction, pathToDraw, true
)
}
drawPath(drawingCache.pathToDraw, checkColor, style = stroke)
}
함수 파라미터에 둘 다 0f가 들어가면 캔버스를 못 그린다.
checkFraction: Float,
crossCenterGravitation: Float,
Checkbox가 unmark 상태일 때 내부 구조상 체크를 그리는 것이 불가능하다.
현재 checkmarkColor() 함수에서 왜 색상체크를 하고 있는지 알 수 없었고(의미가 없는 코드로 보인다.), 이 때문에 삽질을 오래했다..
issueTraker에 올렸다.
구현하고자 하는 체크 인터렉션은 나중에 고민하고, 그냥 벡터 이미지로 구현해야겠다..