Andrew Hughes
10/07/2021, 5:52 PMwrapContentWidth(unbounded = true)
modifier on the Text
composable, however, this has the side-effect of never wrapping the text, which I don't necessarily want. I started looking into creating a transition and using AnimatedContent
but I haven't been having much luck so far.Doris Liu
10/07/2021, 7:56 PMexpandHorizontally() + fadeIn()
and shrinkHorizontally() + fadeOut()
for the text. See: https://developer.android.com/reference/kotlin/androidx/compose/animation/package-summary#expandHorizontally(androidx[β¦]in.Boolean,kotlin.Function1)
I would use AnimatedVisibility for the text instead of AnimatedContent for the two layouts, because there is a shared element between the two layouts -- the orange compose button. We don't currently support shared element yet.rsktash
10/07/2021, 8:48 PMAndrew Hughes
10/07/2021, 11:00 PMAnimatedVisibility
and I was again able to make it work, but I had to use .wrapContentWidth(unbounded = true)
on the Text
composable.
@rsktash Here's a simplified example that demonstrates the issue:
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.animation.core.animateDp
import androidx.compose.animation.core.updateTransition
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.ArrowForward
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
@OptIn(ExperimentalAnimationApi::class)
@Composable
fun SimpleNavRail(
expanded: Boolean,
onExpandClick: () -> Unit,
onCreateClick: () -> Unit,
) {
val transition = updateTransition(targetState = expanded, label = "Expanded")
val width by transition.animateDp(label = "Width") { if (it) 256.dp else 72.dp }
Surface(modifier = Modifier.width(width)) {
Column {
IconButton(
onClick = onExpandClick,
modifier = Modifier.align(Alignment.End)
) {
Icon(
imageVector = if (expanded) Icons.Default.ArrowBack else Icons.Default.ArrowForward,
contentDescription = null, // TODO
modifier = Modifier.size(24.dp),
tint = MaterialTheme.colors.primary,
)
}
Surface(
modifier = Modifier
.padding(8.dp)
.height(56.dp)
.clickable(onClick = onCreateClick),
shape = if (expanded) RoundedCornerShape(33.dp) else CircleShape,
color = MaterialTheme.colors.primary,
) {
Row(
verticalAlignment = Alignment.CenterVertically,
) {
val iconHorizontalPadding by transition.animateDp(label = "FAB Horizontal Padding") { if (it) 12.dp else 16.dp }
Icon(
imageVector = Icons.Default.Add,
contentDescription = null, // TODO
modifier = Modifier
.padding(horizontal = iconHorizontalPadding)
.size(24.dp)
)
transition.AnimatedVisibility(
visible = { expanded -> expanded },
enter = fadeIn(),
exit = fadeOut(),
) {
Text(
text = "Create",
style = MaterialTheme.typography.button,
modifier = Modifier
.padding(end = 20.dp)
.wrapContentWidth(unbounded = true)
)
}
}
}
}
}
}
@Preview
@Composable
private fun SimpleNavRailExpandedPreview() {
var expanded by remember { mutableStateOf(true) }
SimpleNavRail(
expanded = expanded,
onExpandClick = { expanded = !expanded },
onCreateClick = { },
)
}
Andrew Hughes
10/07/2021, 11:00 PM.wrapContentWidth(unbounded = true)
on the Text
composable you'll see that the word "Create" wraps during the transition when the button collapses. It's definitely much less visible in the current iteration than it has been before, but I can't figure out how to do this "properly" without it. And if the button actually needs the text to wrap, I'm not sure how that would work.Andrew Hughes
10/07/2021, 11:06 PMAnimatedVisibility
. π I assume that's just because it's a work-in-progress.
Since I can't inspect the AnimatedVisibility
transition, it would helpful to be able to slow down the entire transition. Is there a way to do that? I've only found ways to slow down individual components of the transition by specifying an animationSpec
.Doris Liu
10/07/2021, 11:11 PMDoris Liu
10/07/2021, 11:12 PMAndrew Hughes
10/07/2021, 11:30 PMDoris Liu
10/07/2021, 11:35 PMexpandFrom
parameter to Alignment.Start
to achieve what you needAndrew Hughes
10/07/2021, 11:45 PMAnimatedVisibility
transition in the animation inspection.Doris Liu
10/07/2021, 11:52 PMAndrew Hughes
10/07/2021, 11:53 PMDoris Liu
10/07/2021, 11:54 PMAndrew Hughes
10/07/2021, 11:54 PMAndrew Hughes
10/07/2021, 11:54 PMDoris Liu
10/07/2021, 11:54 PMAndrew Hughes
10/07/2021, 11:55 PMDoris Liu
10/08/2021, 12:06 AMAndrew Hughes
10/08/2021, 8:54 PMtransition.durationMillis = 5000
). Is that something that's on the roadmap or I should submit a feature request for on the bug tracker?Andrew Hughes
10/08/2021, 8:56 PMSurface
composable. For the expand case, the issue is that the button is not being laid out as if the parent Surface
composable were at the target width (256 dp). Instead, the button is constantly being re-laid out as the nav rail expands, causing the text to reflow (despite the expandHorizontally()
enter transition). Here's a GIF demonstrating what I'm seeing with a long string on the button to make it easier to see.Andrew Hughes
10/08/2021, 8:57 PMDoris Liu
10/08/2021, 8:58 PMAndrew Hughes
10/08/2021, 9:00 PMDoris Liu
10/08/2021, 9:03 PMAndrew Hughes
10/08/2021, 9:04 PMDoris Liu
10/08/2021, 9:07 PMAndrew Hughes
10/08/2021, 9:08 PMSurface
) as a part of the transition. As you can see the AnimatedVisibilty
is working perfectly because the width of the parent isn't interfering.Doris Liu
10/08/2021, 9:09 PMDoris Liu
10/08/2021, 9:10 PMAndrew Hughes
10/08/2021, 9:11 PMDoris Liu
10/08/2021, 9:13 PMAndrew Hughes
10/08/2021, 9:21 PMAndrew Hughes
10/08/2021, 9:30 PMSpacer(modifier = Modifier.width(width))
this causes the parent Surface
to animate to the same width constraints that I was setting directly on the Surface
.Doris Liu
10/08/2021, 9:31 PMAndrew Hughes
10/08/2021, 9:36 PMwrapContentWidth(unbounded = true)
may have sufficed, but I'm also trying to learn the compose animation APIs, so I was hoping there was a way to do this without relying on that. πDoris Liu
10/08/2021, 9:47 PMDoris Liu
10/08/2021, 9:51 PMAndrew Hughes
10/08/2021, 9:51 PMSpacer
that is enforcing the width.Andrew Hughes
10/08/2021, 9:52 PMDoris Liu
10/08/2021, 9:53 PMModifier.animateContentSize
does: https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:compose/[β¦]onMain/kotlin/androidx/compose/animation/AnimationModifier.kt