本文我们将介绍如何在 Jetpack Compose 中实现类似B站这种带有渐变边框的标签或按钮,也进一步介绍了在 Jetpack Compose 中怎样实现渐变边框动画。
1. 渐变色边框
单单至是实现渐变边框很简单,设置带有线性渐变颜色的笔刷作为边框即可:
@Composable
fun GradientBorderChip() {
val colors = listOf(
Color(0xFF326F67),
Color(0xFF503472),
Color(0xFFA5477F),
Color(0xFFE18084),
)
FilterChip(
selected = false,
onClick = { /TODO*/ },
border = BorderStroke(1.dp, Brush.linearGradient(colors)),
label = {
Row(
modifier = Modifier.padding(8.dp),
verticalAlignment = Alignment.CenterVertically,
) {
Icon(
imageVector = Icons.Default.FavoriteBorder,
contentDescription = "favorite",
modifier = Modifier.size(24.dp),
)
Spacer(modifier = Modifier.size(4.dp))
Text(
text = "https://itmob.cn",
maxLines = 3, overflow = TextOverflow.Ellipsis
)
}
},
)
}
上面的代码使用了 material3 中的
FilterChip
组件,设置 border 参数即可,但是在 material3 1.2.0-alpha11 版本之前 border 参数是ChipBorder
类型,只提供了设置边框颜色不能使用 Brush 设置渐变色。
2. 渐变色边框动画
在 Jetpack Compose 中尝试动画边框,可以增强用户界面的视觉效果,提供更好的用户体验。
怎样让渐变色动起来呢?
第一步是定义边框颜色的画刷,使用 Brush.sweepGradient
创建扇形渐变画刷:
// 为边框创建一个扇形渐变画刷。
val brush = Brush.sweepGradient(borderColors)
第二步通过此画刷渲染边框的颜色:
Surface(
modifier = Modifier
.size(64.dp)
.clipToBounds()
.drawWithContent {
drawCircle(
brush = Brush.sweepGradient(colors),
radius = size.width,
blendMode = BlendMode.SrcIn,
)
drawContent()
},
color = Color.Transparent, // 设置透明背景
shape = RoundedCornerShape(8.dp),
content = {},
)
设置透明背景,即可见到扇形渐变的效果
第三步应用 Surface 的背景色
Surface(
modifier = Modifier
.size(64.dp)
.clipToBounds()
.padding(1.dp)
.drawWithContent {
drawCircle(
brush = Brush.sweepGradient(colors),
radius = size.width,
blendMode = BlendMode.SrcIn,
)
drawContent()
},
color = MaterialTheme.colorScheme.surface,
shape = RoundedCornerShape(8.dp),
content = {},
)
设置
Surface
背景色或使用默认颜色,并设置 padding 作为边框宽度
第四步为扇形渐变色添加旋转动画
val colors = listOf(
Color(0xFF326F67),
Color(0xFF503472),
Color(0xFFA5477F),
Color(0xFFE18084),
)
val infiniteTransition = rememberInfiniteTransition(label = "")
val angle by infiniteTransition.animateFloat(
initialValue = 0f,
targetValue = 360f,
animationSpec = infiniteRepeatable(
animation = tween(2500, easing = LinearEasing),
repeatMode = RepeatMode.Restart,
),
label = "",
)
2.1 完整的代码和效果:
@Composable
fun AnimatedGradientBorderChip(
modifier: Modifier = Modifier,
content: @Composable () -> Unit
) {
val colors = listOf(
Color(0xFF326F67),
Color(0xFF503472),
Color(0xFFA5477F),
Color(0xFFE18084),
)
val infiniteTransition = rememberInfiniteTransition(label = "")
val angle by infiniteTransition.animateFloat(
initialValue = 0f,
targetValue = 360f,
animationSpec = infiniteRepeatable(
animation = tween(2500, easing = LinearEasing),
repeatMode = RepeatMode.Restart
),
label = "",
)
Surface(
onClick = { /* TODO */ },
modifier = modifier,
shape = RoundedCornerShape(8.dp),
) {
Surface(
modifier = Modifier
.clipToBounds()
.padding(1.dp)
.drawWithContent {
rotate(angle) {
drawCircle(
brush = Brush.sweepGradient(colors),
radius = size.width,
blendMode = BlendMode.SrcIn,
)
}
drawContent()
},
color = MaterialTheme.colorScheme.background,
shape = RoundedCornerShape(8.dp),
content = content,
)
}
}
调用带有渐变色动画的自定义控件:AnimatedGradientBorderChip
AnimatedGradientBorderChip {
Row(
modifier = Modifier.padding(8.dp),
verticalAlignment = Alignment.CenterVertically,
) {
Icon(
imageVector = Icons.Default.FavoriteBorder,
contentDescription = "favorite",
modifier = Modifier.size(24.dp),
)
Spacer(modifier = Modifier.size(4.dp))
Text(text = "https://itmob.cn")
}
}
效果如下:
其他
Jetpack Compose 中三个绘图修饰符 drawWithContent, drawBehind, drawWithCache 的区别和用法
Jetpack Compose 中 DrawStyle 详解 - (线段/笔画/轮廓的绘制样式)
Jetpack Compose 中 Canvas 绘制图形的基本用法