How to pause progress animation in jetpack compose

Helo folks I am facing this issue on which i need little bit of clearance,

I m trying to implement Horizontal progress basically same as in instagram stories

enter image description here

thing is when user starts scrolling to another story or long presses the story i want to Pause my progressbar animation. I have implemented my progress bar following way

fun HorizontalProgressBar(
    modifier: Modifier = Modifier,
    progressColor: Color = Color.White,
    backGroundColor: Color = Color.White.copy(0.14f),
    progressBarsState: ProgressBarsState = ProgressBarsState.NOT_STARTED,
    index: Int = 0,
    paused: Boolean = false,
    onSliceFinished: () -> Unit,
    ) {

    val initialValue = when (progressBarsState) {
        ProgressBarsState.COMPLETED -> 1f
        else -> 0f
    }
    var progress by remember {
        mutableStateOf(initialValue)
    }

    //using coroutine  to increase progress value for animation purpose
    LaunchedEffect( key1 = paused) {
        if (paused){
            cancel()
        } else {
            if (progressBarsState == ProgressBarsState.PLAYING) {

                while (progress < 1f) {
                    progress += 0.01f
                    delay(20)
                }
                onSliceFinished()
            }
        }
    }
    LinearProgressIndicator(
        progress = progress,
        modifier
            .height(2.dp)
            .clip(YouthAppTheme.shapes.medium),
        progressColor,
        backGroundColor
    )
}

and then from the outside i have pagerState field isScrollInProgress as a compose state so that user starts scrolling pager I would recompose this function with changed paused parameter,

  var scrollInProgress by remember {
                    mutableStateOf(pagerState.isScrollInProgress)
                }

                SlicedProgressBar(
                    2,
                    modifier = Modifier
                        .fillMaxWidth()
                        .height(48.dp),
                    paused = scrollInProgress,
                    spacing = 10.dp
                )

SlicedProgressBar is basically many progressBars together same as it is in instagram stories

@Composable
fun SlicedProgressBar(
    pageCount: Int,
    modifier: Modifier,
    paused: Boolean,
    spacing: Dp,
    onSliceFinished: () -> Unit,
) {

    Row(
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.SpaceBetween,
        modifier = modifier.height(38.dp),
    ) {

        var currentIndex by remember {
            mutableStateOf(0)
        }

        for (index in 0 until pageCount) {

            Spacer(modifier = Modifier.width(20.dp))

            val correctState = when {
                index < currentIndex -> ProgressBarsState.COMPLETED
                index == currentIndex -> ProgressBarsState.PLAYING
                else -> ProgressBarsState.NOT_STARTED
            }


            HorizontalProgressBar(
                modifier = Modifier.weight(1f),
                progressBarsState = correctState,
                index = currentIndex,
                paused = paused
            ) {
                onSliceFinished()
                currentIndex++
            }

        }


    }
}

Nothing happens when paused parameter changes coroutine seems to be continuing working and updating progress values , Is it connected somehow to threading or exactly what am i doing wrong here.

P.s i have tried to use Animatable value for animation and then call .stop() method on it when i want to pause animation but it has no effect whatsoever,

Upvotes: 1

Views: 969

Answers (2)

padPad
padPad

Reputation: 199

you can pause the progress bar from the interactionSource of the pager state, instead of the isScrollInProgress

val isDragged = pagerState.interactionSource.collectIsDraggedAsState()

my code,

   val pagerState =
        rememberPagerState(initialPage = selectedStory, pageCount = { storyList.size })

    HorizontalPager(
        state = pagerState,
        modifier = Modifier
            .fillMaxSize()
            .background(Color.Red),
    ) { page ->

        val isShowed = page == pagerState.settledPage

       
        val shouldPause = pagerState.interactionSource.collectIsDraggedAsState()

 
        YourContent(isShowed, shouldPause) {

           // on story finished
            }
        }
    }

the ProgressBar:

private fun ProgressStoryIndicator(
       shouldPause : Boolean,
       isShowed: Boolean,
       modifier: Modifier = Modifier,
       onAnimationEnd: () -> Unit
) {
  Row (
    modifier = modifier
  ) {

    var progress by remember {
        mutableStateOf(0.00f)
    }

    val animatedProgress by animateFloatAsState(
        targetValue = progress,
        animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec, label = ""
    )

   
    if (isShowed) {
        LaunchedEffect(key1 = shouldPause ) {
            while (progress < 1f && isActive && shouldPause.not()) {
                progress += 0.01f

                delay(50)
            }

            //When the timer is not paused and animation completes then move to next page.
            if (isActive && shouldPause.not()) {
                delay(200)
                onAnimationEnd()
            }
        }
    }
    LinearProgressIndicator(
        progress = animatedProgress,
        modifier = Modifier.fillMaxWidth(),
        color = colorResource(id = R.color.color),
        backgroundColor = Color.White,
        strokeCap = StrokeCap.Round
    )
}

}

Upvotes: 0

bylazy
bylazy

Reputation: 1305

You don't need to remember isScrollInProgress state:

//var scrollInProgress by remember {
//                    mutableStateOf(pagerState.isScrollInProgress)
//                }

                SlicedProgressBar(
                    2,
                    modifier = Modifier
                        .fillMaxWidth()
                        .height(48.dp),
                    paused = pagerState.isScrollInProgress,
                    spacing = 10.dp
                )

Upvotes: 0

Related Questions