我们如何在 Jetpack Compose 中创建一个圆形复选框?
how can we create a circular checkbox in jetpack compose?
通常可以使用修饰符将不同的形状分配给可组合项,但在此可组合项中并未这样做。
我要图中标记的部分是一个圆圈
你可以看下面我写的代码
@Composable
fun StandardCheckbox(
text: String = "",
checked: Boolean,
onCheckedChange: ((Boolean) -> Unit)?,
) {
Row(
Modifier.padding(horizontal = SpaceMedium)
) {
Checkbox(
modifier = Modifier
.clip(CircleShape),
checked = checked,
onCheckedChange = onCheckedChange,
enabled = true,
colors = CheckboxDefaults.colors(
checkedColor = MaterialTheme.colors.primary,
checkmarkColor = MaterialTheme.colors.onPrimary,
uncheckedColor = MaterialTheme.colors.onBackground.copy(alpha = 0.3f)
)
)
Spacer(modifier = Modifier.width(SpaceSmall))
Text(
text = text,
color = MaterialTheme.colors.primary,
modifier = Modifier.clickable {
if (onCheckedChange != null) {
onCheckedChange(!checked)
}
}
)
}
}
下面的代码来自CheckboxImpl
composable
Canvas(modifier.wrapContentSize(Alignment.Center).requiredSize(CheckboxSize)) {
val strokeWidthPx = floor(StrokeWidth.toPx())
drawBox(
boxColor = boxColor,
borderColor = borderColor,
radius = RadiusSize.toPx(),
strokeWidth = strokeWidthPx
)
drawCheck(
checkColor = checkColor,
checkFraction = checkDrawFraction,
crossCenterGravitation = checkCenterGravitationShiftFraction,
strokeWidthPx = strokeWidthPx,
drawingCache = checkCache
)
}
drawBox
将始终绘制一个圆角矩形。无法定制。
要实现圆形复选框,您需要编写自定义 Composable
并绘制圆形而不是矩形。您可以使用 RadioButton
和 CheckboxImpl
组合作为参考。
为了实现原生体验的圆形复选框,同时保留主体颜色和点击波纹效果,保持简洁,IconButton是最佳选择。
@Composable
fun CircleCheckbox(selected: Boolean, enabled: Boolean = true, onChecked: () -> Unit) {
val color = MaterialTheme.colorScheme
val imageVector = if (selected) Icons.Filled.CheckCircle else Icons.Outlined.Circle
val tint = if (selected) color.primary.copy(alpha = 0.8f) else color.white.copy(alpha = 0.8f)
val background = if (selected) color.white else Color.Transparent
IconButton(onClick = { onChecked() },
modifier = Modifier.offset(x = 4.dp, y = 4.dp),
enabled = enabled) {
Icon(imageVector = imageVector, tint = tint,
modifier = Modifier.background(background, shape = CircleShape),
contentDescription = "checkbox")
}
}
通常可以使用修饰符将不同的形状分配给可组合项,但在此可组合项中并未这样做。
我要图中标记的部分是一个圆圈
你可以看下面我写的代码
@Composable
fun StandardCheckbox(
text: String = "",
checked: Boolean,
onCheckedChange: ((Boolean) -> Unit)?,
) {
Row(
Modifier.padding(horizontal = SpaceMedium)
) {
Checkbox(
modifier = Modifier
.clip(CircleShape),
checked = checked,
onCheckedChange = onCheckedChange,
enabled = true,
colors = CheckboxDefaults.colors(
checkedColor = MaterialTheme.colors.primary,
checkmarkColor = MaterialTheme.colors.onPrimary,
uncheckedColor = MaterialTheme.colors.onBackground.copy(alpha = 0.3f)
)
)
Spacer(modifier = Modifier.width(SpaceSmall))
Text(
text = text,
color = MaterialTheme.colors.primary,
modifier = Modifier.clickable {
if (onCheckedChange != null) {
onCheckedChange(!checked)
}
}
)
}
}
下面的代码来自CheckboxImpl
composable
Canvas(modifier.wrapContentSize(Alignment.Center).requiredSize(CheckboxSize)) {
val strokeWidthPx = floor(StrokeWidth.toPx())
drawBox(
boxColor = boxColor,
borderColor = borderColor,
radius = RadiusSize.toPx(),
strokeWidth = strokeWidthPx
)
drawCheck(
checkColor = checkColor,
checkFraction = checkDrawFraction,
crossCenterGravitation = checkCenterGravitationShiftFraction,
strokeWidthPx = strokeWidthPx,
drawingCache = checkCache
)
}
drawBox
将始终绘制一个圆角矩形。无法定制。
要实现圆形复选框,您需要编写自定义 Composable
并绘制圆形而不是矩形。您可以使用 RadioButton
和 CheckboxImpl
组合作为参考。
为了实现原生体验的圆形复选框,同时保留主体颜色和点击波纹效果,保持简洁,IconButton是最佳选择。
@Composable
fun CircleCheckbox(selected: Boolean, enabled: Boolean = true, onChecked: () -> Unit) {
val color = MaterialTheme.colorScheme
val imageVector = if (selected) Icons.Filled.CheckCircle else Icons.Outlined.Circle
val tint = if (selected) color.primary.copy(alpha = 0.8f) else color.white.copy(alpha = 0.8f)
val background = if (selected) color.white else Color.Transparent
IconButton(onClick = { onChecked() },
modifier = Modifier.offset(x = 4.dp, y = 4.dp),
enabled = enabled) {
Icon(imageVector = imageVector, tint = tint,
modifier = Modifier.background(background, shape = CircleShape),
contentDescription = "checkbox")
}
}