Jetpack Compose实现类似Pulsator4Droid的流动脉冲动画需求
Jetpack Compose实现Pulsator4Droid风格流动脉冲动画
现有代码
当前实现仅让圆形小幅缩放,无法达到向外扩散淡出的脉冲效果:
@Composable fun PulseView() { val infiniteTransition = rememberInfiniteTransition() val smallCircleSizeInPx = LocalDensity.current.run { 6.dp.toPx() } val mediumCircleSize by infiniteTransition.animateValue( initialValue = 13.dp, targetValue = 11.dp, Dp.VectorConverter, animationSpec = infiniteRepeatable( animation = tween(500), repeatMode = RepeatMode.Reverse ) ) val largeCircleSize by infiniteTransition.animateValue( initialValue = 18.dp, targetValue = 16.dp, Dp.VectorConverter, animationSpec = infiniteRepeatable( animation = tween(500), repeatMode = RepeatMode.Reverse ) ) val middleCircleSizeInPx = LocalDensity.current.run { mediumCircleSize.toPx() } val largeCircleSizeInPx = LocalDensity.current.run { largeCircleSize.toPx() } val strokeWidth = LocalDensity.current.run { 2.dp.toPx() } val brush = Brush.linearGradient(listOf(NeutralsCloudy, NeutralsCloudy)) PulseViewContent( smallCircleSizeInPx, middleCircleSizeInPx, largeCircleSizeInPx, strokeWidth, brush, ) } @Composable fun PulseViewContent(smallCircleSizeInPx: Float, middleCircleSizeInPx: Float, largeCircleSizeInPx: Float, strokeWidth: Float, brush: Brush) { Canvas(modifier = Modifier.fillMaxHeight()) { drawIntoCanvas { drawLine( brush = brush, start = Offset(x = size.width / 2, y = 0F), end = Offset(x = size.width / 2, y = size.height / 2), strokeWidth = strokeWidth, ) drawLine( brush = brush, start = Offset(x = size.width / 2, y = size.height / 2), end = Offset(x = size.width / 2, y = size.height), strokeWidth = strokeWidth, ) drawCircle( color = SeaGreen.copy(alpha = 0.32f), radius = largeCircleSizeInPx, center = Offset(size.width, size.height / 2) ) drawCircle( color = SeaGreen.copy(alpha = 0.32f), radius = middleCircleSizeInPx, center = Offset(size.width, size.height / 2) ) drawCircle( color = SeaGreen, radius = smallCircleSizeInPx, center = Offset(size.width, size.height / 2) ) } } }
效果说明
- 实际效果:几个圆形在固定大小范围内小幅往复缩放,无流动扩散感
- 预期效果:多个圆形从中心向外逐渐扩散,同时透明度递减,循环产生连续的脉冲流动效果
修改后的实现方案
以下代码实现了类似Pulsator4Droid的流动脉冲效果,核心是让多个脉冲层按不同延迟启动,同时进行缩放和透明度动画:
import androidx.compose.animation.core.* import androidx.compose.foundation.Canvas import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp // 自定义颜色,替换为你的颜色值 val SeaGreen = Color(0xFF2ECC71) val NeutralsCloudy = Color(0xFFBDC3C7) @Composable fun PulsatorView() { val pulseCount = 3 // 脉冲层数 val pulseDuration = 1500 // 单个脉冲动画时长(毫秒) val maxPulseRadius = 30.dp // 脉冲最大扩散半径 Canvas(modifier = Modifier.fillMaxSize()) { val center = Offset(size.width, size.height / 2) val maxRadiusPx = maxPulseRadius.toPx() val smallCircleRadius = 6.dp.toPx() // 绘制中心固定小圆圈 drawCircle( color = SeaGreen, radius = smallCircleRadius, center = center ) // 绘制竖线 val strokeWidth = 2.dp.toPx() drawLine( color = NeutralsCloudy, start = Offset(x = size.width / 2, y = 0f), end = Offset(x = size.width / 2, y = size.height), strokeWidth = strokeWidth ) // 绘制多个脉冲层 repeat(pulseCount) { index -> val delay = (index * pulseDuration / pulseCount).toInt() val infiniteTransition = rememberInfiniteTransition(label = "pulse_$index") // 缩放动画:从0到1(对应半径从0到maxRadiusPx) val scale by infiniteTransition.animateFloat( initialValue = 0f, targetValue = 1f, animationSpec = infiniteRepeatable( animation = tween(pulseDuration, delayMillis = delay), repeatMode = RepeatMode.Restart ), label = "scale_$index" ) // 透明度动画:从1到0 val alpha by infiniteTransition.animateFloat( initialValue = 1f, targetValue = 0f, animationSpec = infiniteRepeatable( animation = tween(pulseDuration, delayMillis = delay), repeatMode = RepeatMode.Restart ), label = "alpha_$index" ) drawCircle( color = SeaGreen.copy(alpha = alpha), radius = maxRadiusPx * scale, center = center ) } } }
关键实现细节
- 多脉冲层错开启动:通过给每个脉冲层设置不同的
delayMillis,让脉冲依次向外扩散,形成连续流动的效果 - 缩放+透明度联动动画:每个脉冲从0半径开始放大到最大半径,同时透明度从1降到0,模拟扩散淡出的视觉效果
- 简化Canvas绘制:将所有绘制逻辑整合到一个Canvas中,减少组件层级,提升性能
- 可配置参数:通过
pulseCount、pulseDuration、maxPulseRadius可以灵活调整脉冲的数量、速度和大小
内容的提问来源于stack exchange,提问作者Compose Learner
相关产品推荐
相关产品推荐

