Vivek Modi
Vivek Modi

Reputation: 7181

Flow pulse animation in jetpack compose

I want to build flow pulse animation. I build something similar to that but that one is not accurate what I want for my requirement. I want something like this library.

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

PulseViewContent

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

Actual Output

You can find in the Youtube.

Expected Output

You can find in the Youtube.

Upvotes: 1

Views: 883

Answers (1)

Vivek Modi
Vivek Modi

Reputation: 7181

I solve this problem with the help of this solution

@Preview(showBackground = true)
@Composable
fun PulseAnimation() {
    Box(
        contentAlignment = Alignment.Center,
        modifier = Modifier.fillMaxSize()
    ) {
        val transition = rememberInfiniteTransition()
        val duration = 3_000
        val count = 3
        val progress = List(3) {
            transition.animateFloat(
                initialValue = 0f,
                targetValue = 1f,
                animationSpec = InfiniteRepeatableSpec(
                    animation = tween(durationMillis = duration, easing = LinearEasing),
                    initialStartOffset = StartOffset(it * duration / count),
                    repeatMode = RepeatMode.Restart,
                )
            )
        }
        Canvas(modifier = Modifier.fillMaxHeight()) {
            val radius = 40.dp.toPx() / 2f
            drawLine(
                color = Color.Black,
                start = Offset(x = size.width / 2, y = 0F),
                end = Offset(x = size.width / 2, y = size.height / 2),
                strokeWidth = 2.dp.toPx(),
            )
            progress.forEach {
                drawCircle(
                    color = Color.Magenta.copy(alpha = 1f - it.value),
                    radius = radius * it.value,
                    center = Offset(size.width, size.height / 2)
                )
            }
        }
    }
}

If anyone know better solution. Please free to update or provide solution. Thanks

Upvotes: 0

Related Questions