大家好,我正面临这个问题,我需要一些许可,
我正在尝试实现与 Instagram 故事中基本相同的水平进度
事情是当用户开始滚动到另一个故事或长按故事时我想暂停我的进度条动画。我已经按照以下方式实现了进度条
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
)
}
然后从外部我将 pagerState 字段 isScrollInProgress 作为撰写状态,以便用户开始滚动寻呼机我将使用更改的暂停参数重新组合此函数,
var scrollInProgress by remember {
mutableStateOf(pagerState.isScrollInProgress)
}
SlicedProgressBar(
2,
modifier = Modifier
.fillMaxWidth()
.height(48.dp),
paused = scrollInProgress,
spacing = 10.dp
)
SlicedProgressBar 基本上是许多进度条放在一起,就像在 Instagram 故事中一样
@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++
}
}
}
}
当暂停的参数更改协程似乎继续工作并更新进度值时,什么也没有发生, 它是否以某种方式与线程相关,或者我在这里做错了什么。
P.s 我尝试使用 Animatable 值进行动画,然后当我想暂停动画时调用 .stop() 方法,但它没有任何效果,
您无需记住
isScrollInProgress
状态:
//var scrollInProgress by remember {
// mutableStateOf(pagerState.isScrollInProgress)
// }
SlicedProgressBar(
2,
modifier = Modifier
.fillMaxWidth()
.height(48.dp),
paused = pagerState.isScrollInProgress,
spacing = 10.dp
)
您可以从寻呼机状态的interactionSource暂停进度条,而不是isScrollInProgress
val isDragged = pagerState.interactionSource.collectIsDraggedAsState()
我实现了进度条,有点不同,但我们遇到了同样的问题 检查我下面的代码,
val pagerState =
rememberPagerState(initialPage = selectedStory, pageCount = { storyList.size })
HorizontalPager(
state = pagerState,
modifier = Modifier
.fillMaxSize()
.background(Color.Red),
) { page ->
val isShowed = page == pagerState.settledPage
val storyPage = storyList[page]
val shouldPause = pagerState.interactionSource.collectIsDraggedAsState()
YourContent(storyPage, onCtaClicked, isShowed, shouldPause) {
// on story finished
}
}
}
进度条:
private fun ProgressStoryIndicator(
storyModel: StoryModel,
shouldPause : Boolean,
shouldStart: 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 (shouldStart) {
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
)
}
}