Как сделать blur на бекграунде Canvas?
Есть вот такая иконка
она рисуется вот так:
@Composable
private fun IconWithCircleBackground(
@DrawableRes res: Int,
modifier: Modifier = Modifier,
radius: Dp = 16.dp,
strokeColor: Color = ColorTokens.grey_10,
strokeWidth: Dp = 1.dp,
backgroundColor: Color = Color.Black,
backgroundAlpha: Float = 0.7f
) {
Box(modifier = modifier.size(radius)) {
Canvas(modifier = Modifier.size(radius)) {
drawCircle(
color = backgroundColor.copy(alpha = backgroundAlpha),
radius = radius.toPx() - strokeWidth.toPx() / 2
)
drawCircle(
color = strokeColor,
radius = radius.toPx(),
style = Stroke(width = strokeWidth.toPx())
)
}
Image(
painter = painterResource(id = res),
contentDescription = stringResource(id = ...)
)
}
}
То есть есть Canvas
на кортором отрисовывается первый слой как бекграунд в форме окружности заполненый черным цветом (+ альфа), и вторым слоем отрисовывается белая линия как граница и в центре располагается иконка.
Нужно сделать первый слой (черный бекграунд), чтоб он был blur. Вопрос - как можно применить blur тут?
Ответы (2 шт):
Размытие на основе RenderScript
, радиусом задается глубина размытия:
Bitmap bm_out = Bitmap.createBitmap( bm_in );
RenderScript rs = RenderScript.create(context);
ScriptIntrinsicBlur theIntrinsic = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
Allocation alloc_in = Allocation.createFromBitmap(rs, bm_in);
Allocation alloc_out = Allocation.createFromBitmap(rs, bm_out );
theIntrinsic.setRadius( radius );
theIntrinsic.setInput(alloc_in);
theIntrinsic.forEach(alloc_out);
alloc_out.copyTo( bm_out );
Более примитивный вариант - это просто уменьшить исходный Bitmap
раз в 8-16 а потом "растянуть" его на canvas
.
В итоге я сделал это так (спойлер - блюр не помог мне сделать то что я хотел, то что я хотел это все же гласморфик, но может кому то пригодится)
@Composable
private fun IconWithCircleBackground(
@DrawableRes res: Int,
modifier: Modifier = Modifier,
radius: Dp = 32.dp,
strokeColor: Color = ColorTokens.grey_10,
strokeWidth: Dp = 2.dp,
backgroundColor: Color = Color.Black,
backgroundAlpha: Float = 0.8f
) {
Box(
modifier = modifier
.size(radius)
.clip(CircleShape)
) {
// Background
Image(
modifier = modifier
.fillMaxSize()
.blur(radius = 10.dp)
,
bitmap = coloredBitmap(color = backgroundColor, alpha = backgroundAlpha).asImageBitmap(),
contentDescription = null
)
// Stroke
Canvas(modifier = Modifier.matchParentSize()) {
drawCircle(
color = strokeColor,
radius = size.minDimension / 2,
style = Stroke(width = strokeWidth.toPx())
)
}
Image(
modifier = Modifier.align(Alignment.Center),
painter = painterResource(id = res),
contentDescription = stringResource(id = ...)
)
}
}
Идея в том, что есть такой модифаер blur(radius = 10.dp)
, но его нельзя применить для drawCircle
, поэтому я создаю битмап, вставляю его в Image
и на Image
уже применяю blur
через модифаер.