ITmob-Ly
发布于 2024-08-07 / 183 阅读
0

怎样在 Jetpack Compose 中实带有渐变色动画的边框?

本文我们将介绍如何在 Jetpack Compose 中实现类似B站这种带有渐变边框的标签或按钮,也进一步介绍了在 Jetpack Compose 中怎样实现渐变边框动画。

Gradient border

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
                )
            }
        },
    )
}

Gradient Chip

上面的代码使用了 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 = {},
)

设置透明背景,即可见到扇形渐变的效果

SurfacewithsweepGradient.JPG

第三步应用 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 作为边框宽度

SurfacewithsweepGradientborder.JPG

第四步为扇形渐变色添加旋转动画

    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")
    }
}

效果如下:

Chip with animated gradient border

其他

Jetpack Compose 中三个绘图修饰符 drawWithContent, drawBehind, drawWithCache 的区别和用法

Jetpack Compose 中 DrawStyle 详解 - (线段/笔画/轮廓的绘制样式)

Jetpack Compose 中 Canvas 绘制图形的基本用法

Jetpack Compose 怎样实现跑马灯效果(Marquee)

Jetpack Compose 实现展开折叠显示更多文本的动画效果