One Off the Slack: Delaying a Progress Indicator

Colton Idle asked:

How would you handle a not showing a progress bar until like 300ms has gone by?

This is a reasonably common request. It avoids showing an indicator that would be removed right away.

Google’s Doris Liu responded:

You pretty much have two options here: 1) Achieve that delay via animation delay, 2) manage the delayed state change outside of animation, which is useful when the delayed state change affects multiple components.

It’s important to consider the “interruption” case: during this delay, could there be another state change (e.g. some form of dismiss or cancel) that could cause the progress bar to never show? AnimatedVisibility can handle that just fine, as it’s effectively an interruption to the delayed animation. But if you were to launch a coroutine to achieve that delayed showing, you’ll need to make sure the job is canceled when you decide to not show at all for various reasons. LaunchedEffect could be helpful for automatically canceling the old job:

var showProgressBar by remember { mutableStateOf(false) }
var isLoaded by remember { mutableStateOf(false) }
LaunchedEffect(isLoaded) {
   if (isLoaded) { 
        launch {
            delay(300)
            showProgressBar = true 
       } 
   } else {
      showProgressBar = false
   }
}

…while Zach Klippenstien offered:

For simple cases you could even use produceState I think:

var isLoaded by remember { mutableStateOf(false) }
val showProgressBar by produceState(initialValue = false, key1 = isLoaded) {
  if (isLoaded) {
    delay(300)
    value = true
  } else {
    value = false
  }
}

Read the original thread in the kotlinlang Slack workspace. Not a member? Join that Slack workspace here!