ursus
10/14/2023, 11:39 PMCrossfade
different from AnimatedContent
? seems weird to have such composable, when crossfade animation is just one example of a transition, you can input into AnimatedContent
Or why is it special?Francesc
10/14/2023, 11:50 PMCrossfade
is to swap between different composables. AnimatedContent
is to animate adding/removing or chaging the size of contentursus
10/14/2023, 11:51 PMFrancesc
10/14/2023, 11:51 PMursus
10/14/2023, 11:53 PMAnimatedContent(someEnum) {
when (it) {
FOO -> FooScreen()
BAR -> BarScreen()
}
}
this is how's it used in the docstransitionSpec = {
fadeIn(
animationSpec = tween(3000)
) togetherWith fadeOut(animationSpec = tween(3000))
},
Francesc
10/14/2023, 11:55 PMursus
10/14/2023, 11:56 PMCrossfade
, and if you look at the sources, its not convenience api for
AnimatedContent(
state,
transitionSpec = {
fadeIn(
animationSpec = tween(3000)
) togetherWith fadeOut(animationSpec = tween(3000))
},
which is what one would expect (even though if it were, not worth it imo)Francesc
10/14/2023, 11:58 PMursus
10/14/2023, 11:58 PMFrancesc
10/14/2023, 11:59 PMursus
10/15/2023, 12:00 AMtransitionSpec: AnimatedContentTransitionScope<S>.() -> ContentTransform = {
(fadeIn(animationSpec = tween(220, delayMillis = 90)) +
scaleIn(initialScale = 0.92f, animationSpec = tween(220, delayMillis = 90)))
.togetherWith(fadeOut(animationSpec = tween(90)))
},
Francesc
10/15/2023, 12:01 AMursus
10/15/2023, 12:02 AMAnimatedContent
plus just fadeIn+fadeOut in the docs, doesnt workFrancesc
10/15/2023, 12:03 AMursus
10/15/2023, 12:03 AMFrancesc
10/15/2023, 12:06 AMAnimatedVisibility(
visible = value != null
) {
Text(value.orEmpty())
)
ursus
10/15/2023, 12:09 AMAnimatedContent(
targetState = error,
transitionSpec = { fadeIn() togetherWith fadeOut() },
label = ""
) {
if (it != null) {
Text(
text = it,
color = MaterialTheme.colors.onErrorBackground,
style = MaterialTheme.typography.caption,
maxLines = 1
)
} else {
Box(modifier = Modifier.width(120.dp).height(16.dp))
}
}
then it looks the way I intended, but obviously I don't know the size, and knowing it defeats the purpose of the whole thing..AnimatedVisibility
I spoke to soon, its because thats what the animation is, if I override it to just fadeinout
AnimatedVisibility(visible = error != null, enter = fadeIn(), exit = fadeOut()) {
Text(
text = error ?: "",
color = MaterialTheme.colors.onErrorBackground,
style = MaterialTheme.typography.caption,
maxLines = 1
)
}
then it works as expectedFrancesc
10/15/2023, 12:14 AMAnimatedVisibility(
visible = value != null,
enter = fadeIn(),
exit = fadeOut(),
)
ursus
10/15/2023, 12:14 AM""
if (someState != null) {
Hint(someState)
}
why is this so hard..Francesc
10/15/2023, 12:19 AMursus
10/15/2023, 12:21 AMif (someState != null) {
Hint(someState)
}
like this?
AnimatedContent(
targetState = someState,
transitionSpec = { slideIn() togetherWith slideOut() }
) {
if (it != null) {
Hint(it)
}
}
Francesc
10/15/2023, 12:23 AMSomeState
as a sealed class,
sealed interface MyWrapper {
data object IDontHaveAValue : MyWrapper
data class MyState(val ...) : MyWrapper
}
AnimatedVisibility(
visible = state.myWrapper is MyWrapper.MyState
) {
MyStateComposable(state.myWrapper)
}
ursus
10/15/2023, 12:25 AMMyStateComposable
will take MyState
as argument
so then you need a cast, and that will crashif (someState != null) {
Hint(someState)
}
this is what you're trying to animate, simple requirementFrancesc
10/15/2023, 12:27 AMursus
10/15/2023, 12:27 AMAnimatedContent(
targetState = error,
transitionSpec = {
slideInHorizontally() togetherWith slideOutHorizontally()
}, label = ""
) {
if (it != null) {
Text(
text = it,
color = MaterialTheme.colors.onErrorBackground,
style = MaterialTheme.typography.caption,
maxLines = 1
)
}
}
is this what you'd expect?Francesc
10/15/2023, 12:36 AM@Preview(widthDp = 420, heightDp = 360)
@Composable
fun PreviewAnimatedContent() {
SampleTheme {
var visible by remember { mutableStateOf(false) }
Surface(
color = MaterialTheme.colorScheme.background,
) {
Column(
modifier = Modifier.padding(all = 16.dp),
horizontalAlignment = Alignment.CenterHorizontally,
) {
AnimatedContent(targetState = visible, label = "animate") {
if (it) {
Text(
text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris tempor nibh vitae est tincidunt, quis ornare lacus pulvinar. Donec non pretium metus. Fusce in libero facilisis, scelerisque magna id, maximus arcu. Vestibulum pellentesque ex nec dui condimentum, sit amet iaculis sapien porttitor. Nunc molestie est non congue lacinia."
)
}
}
Button(onClick = { visible = !visible }) {
Text(
text = "Toggle"
)
}
}
}
}
}
ursus
10/15/2023, 12:37 AMFrancesc
10/15/2023, 12:41 AMAnimatedContent(
targetState = visible,
transitionSpec = {
fadeIn().togetherWith(fadeOut())
},
label = "animate",
ursus
10/15/2023, 12:44 AMFrancesc
10/15/2023, 12:44 AMursus
10/15/2023, 12:45 AMFrancesc
10/15/2023, 12:46 AMursus
10/15/2023, 12:47 AMFrancesc
10/15/2023, 12:47 AMursus
10/15/2023, 12:48 AMFrancesc
10/15/2023, 12:48 AMursus
10/15/2023, 12:48 AMZoltan Demant
10/15/2023, 6:11 AM@Composable
inline fun <T> TransitionValue(
value: T?,
modifier: Modifier = Modifier,
effect: Effect = Fade,
crossinline content: @Composable (T) -> Unit,
) {
val ref = remember {
Ref<T>()
}.also { ref ->
ref.value = value ?: ref.value
}
TransitionVisibility(
modifier = modifier,
visible = value != null,
effect = effect,
content = {
ref.value?.let { value ->
content(value)
}
},
)
}
vide
10/15/2023, 9:38 AMusing
, eg.
transitionSpec = { fadeIn() togetherWith fadeOut() using null }
ursus
10/15/2023, 4:05 PMAnimatedContent(value) {
if (it != null) {
Something(it)
}
}
Zoltan Demant
10/15/2023, 4:42 PM