Rick Regan
03/12/2021, 8:43 PMCrossfade
on a Text
when it is set to the empty string, but not when it is updated in any other way.
This code will crossfade for every update to the state 'text'
Crossfade(targetState = text, animationSpec = tween(1000)) { newText ->
Text(text = newText)
}
but I'd only like it to apply when 'text' is cleared. Is it possible to do this with Crossfade, or do I need some other animation mechanism? (I didn't expect using if (text.isEmpty())
with a crossfaded Text in the if
and just a Text in the else
to work, but I tried it anyway and it didn't.)Adam Powell
03/12/2021, 8:57 PMAnimatedVisibility
might be more appropriate for this use caseRick Regan
03/12/2021, 8:58 PMRick Regan
03/12/2021, 10:20 PMAnimatedVisibility()
is going to do it because with parameter visible = text.isNotEmpty()
, the animation kicks in when the text is empty, which I is what I want, but then there's nothing to animate (empty string).
Even if I could get AnimatedVisibility()
to work for Text, I don't know what I would use for Slider, which is the other widget I would like to fade to a new setting (but only upon "resetting" it through a button, not during interaction with the thumb).Doris Liu
03/13/2021, 12:01 AMAnimatedVisibility
content body
AnimatedVisibility(visible = text.isNotEmpty()) {
var textToDisplay by remember { mutableStateOf(text) }
if (text.isNotEmpty) { textToDisplay = text }
Text(text)
}
Hmm... this may be a useful pattern.Doris Liu
03/13/2021, 12:02 AMRick Regan
03/13/2021, 1:01 AMremember
(coded as below) looks pretty good.
AnimatedVisibility(
visible = text.isNotEmpty(),
enter = fadeIn(animationSpec = tween(1000)),
exit = fadeOut(animationSpec = tween(1000))
) {
var textToDisplay by remember { mutableStateOf(text) }
if (text.isNotEmpty()) { textToDisplay = text }
Text(textToDisplay)
}
Rick Regan
03/13/2021, 1:05 AM@Composable
fun AnimateSlider(
) {
var sliderPosition by remember { mutableStateOf(0f) }
Column {
Crossfade(targetState = sliderPosition, animationSpec = tween(2000)) { newSliderPosition ->
Slider(
value = newSliderPosition,
onValueChange = { sliderPosition = it },
valueRange = 0f..100f,
steps = 5
)
}
Button(
onClick = {sliderPosition = 0f }
) {
Text(text = "Reset")
}
}
}
I don't know if I could do this with the current low-level animation APIs, but I will look into it.Doris Liu
03/13/2021, 1:05 AMtextToDisplay
has the same lifecycle as Text
below - i.e. disposed after animating out.Doris Liu
03/13/2021, 1:28 AMvalue
and onValueChnage
, and use that object as the targetState for Crossfade
. When reset button is clicked, create a new object.Doris Liu
03/13/2021, 1:31 AMRick Regan
03/13/2021, 3:47 AMAnimatedVisibility
pattern is, I realize now that I've plugged it into my app (instead of my Compose test project) it doesn't give me what I'm looking for. It will remove the whole Text
(of course), including the borders (I have a Text of specified size with a border that I want to stick around when the text is cleared). Crossfade on the text value at least just affects that, and leaves everything else (e.g., modifier) alone. (But I'll put this trick in the bank for some possible future use.)Rick Regan
03/13/2021, 5:03 AMtargetState
object for Slider. It doesn't crossfade for normal operation because the changing slider position is hidden inside the object.
As far as registering on the wrong slider, I don't see the issue: if I touch it during animation, it just gets recorded in that new object, right? It effectively overrides the reset, which should be OK. Aside from seeing the right side thumb fading while the new one appears (I tested with a long tween
time), it appears to work.Rick Regan
03/13/2021, 5:41 AM