Rick Regan
07/10/2023, 2:17 PManimateScrollTo()
to vertically scroll a fixed height Text
. The animation occurs as expected when the text length increases past the bottom of the Text
but not when it decreases. I’d like to know how to get it to animate for the latter. (Please see code and screen recording in thread.)Rick Regan
07/10/2023, 2:18 PM@Composable
fun AnimateScrollToOnlyForwards() {
var text by remember { mutableStateOf("") }
val scrollState = rememberScrollState()
Column(modifier = Modifier.padding(20.dp)) {
Text(
modifier = Modifier
.height(42.dp)
.width(100.dp)
.border(
BorderStroke(
width = 1.dp,
color = Color.Black
)
)
.verticalScroll(scrollState)
.padding(4.dp),
text = text
)
Button(
modifier = Modifier.padding(30.dp),
onClick = {
val digit = "${Random.nextInt(48, 58).toChar()}"
text += digit
}
) {
Text(
text = "Add digit",
color = Color.White
)
}
Button(
modifier = Modifier.padding(30.dp),
onClick = { text = text.substring(0, text.length - 1) }
) {
Text(
text = "Remove digit",
color = Color.White
)
}
}
LaunchedEffect(scrollState.maxValue) {
println("Launched Effect, scrollState.maxValue = ${scrollState.maxValue}")
scrollState.animateScrollTo(
value = scrollState.maxValue,
animationSpec = tween(2000) // This spec added just for demonstration purposes, to lengthen animation time
)
}
}
Rick Regan
07/10/2023, 2:18 PMephemient
07/10/2023, 6:49 PMRick Regan
07/10/2023, 7:35 PM.padding()
and .height()
(first I tried one, then the other, then both) before the .verticalScroll() …it didn’t help.ephemient
07/10/2023, 7:36 PMRick Regan
07/10/2023, 7:48 PM.height()
after made it not scroll for some reason, and putting more`.padding()` after didn’t help. Thanks for the suggestions though.Dmitriy Gaiduk
07/13/2023, 11:08 AMModifier.animateContentSize()
Text(
modifier = Modifier
.height(42.dp)
.width(100.dp)
.border(
BorderStroke(
width = 1.dp,
color = Color.Black
)
)
.verticalScroll(scrollState)
.animateContentSize(
animationSpec = tween(durationMillis = 2000)
)
.padding(4.dp),
text = text
)
Rick Regan
07/13/2023, 4:10 PM.animateContentSize()
as you suggested (with no parameters, since the animationSpec was just for demo purposes) and switched to scrollTo()
instead of animateScrollTo()
and it works like I was hoping — at least in this simplified demo.
What’s interesting though is that I can’t get it to work quite like that in my app. It needs a second added character to scroll, and sometimes even a third character to get it to fully scroll. I’ll look more into that.Dmitriy Gaiduk
07/14/2023, 10:28 AManimateScrollTo()
function works as expected.
• When the text becomes smaller, the space for the text decreases instantly. The animateScrollTo()
function does nothing because the text is already at the bottom. Therefore, there is no animation in this case.
How can you solve the problem:
• When the text gets bigger, use the animateScrollTo()
function. Do not call animateContentSize()
.
• When the text gets smaller, use the animateContentSize()
function. Do not call animateScrollTo()
.
Perhaps the combination of animateScrollTo()
and animateContentSize()
does not give a good result. Because every height change in the animateContentSize()
animation triggers LaunchedEffect(scrollState.maxValue)
.Dmitriy Gaiduk
07/14/2023, 10:29 AMfun Modifier.scrollToBottom() =
layout { measurable, constraints ->
val placeable = measurable.measure(
constraints.copy(maxHeight = Constraints.Infinity)
)
layout(constraints.maxWidth, constraints.maxHeight) {
placeable.placeRelative(0, constraints.maxHeight - placeable.height)
}
}
@Composable
fun AnimateScrollToOnlyForwards() {
var text by remember { mutableStateOf("") }
Column(modifier = Modifier.padding(20.dp)) {
Spacer(modifier = Modifier.height(56.dp))
Row {
Box(
modifier = Modifier
.height(42.dp)
.width(100.dp)
.border(
BorderStroke(
width = 1.dp,
color = Color.Black
)
)
.clip(RectangleShape)
) {
Text(
modifier = Modifier
.fillMaxWidth()
.height(42.dp)
.scrollToBottom()
.animateContentSize(
animationSpec = tween(durationMillis = 2000)
),
text = text
)
}
Spacer(modifier = Modifier.width(56.dp))
Box(
modifier = Modifier
.height(42.dp)
.width(100.dp)
.border(
BorderStroke(
width = 1.dp,
color = Color.Black
)
)
) {
Text(
modifier = Modifier
.fillMaxWidth()
.height(42.dp)
.scrollToBottom()
.animateContentSize(
animationSpec = tween(durationMillis = 2000)
)
.background(color = Color.Gray),
text = text
)
}
}
Button(
modifier = Modifier.padding(30.dp),
onClick = {
val digit = "${Random.nextInt(48, 58).toChar()}"
text += digit
}
) {
Text(
text = "Add digit",
color = Color.White
)
}
Button(
modifier = Modifier.padding(30.dp),
onClick = { text = text.substring(0, text.length - 1) }
) {
Text(
text = "Remove digit",
color = Color.White
)
}
}
}
Rick Regan
07/14/2023, 7:21 PManimateScrollTo()
work like I had wished.ephemient
07/15/2023, 1:45 AMephemient
07/15/2023, 1:46 AMephemient
07/15/2023, 1:47 AMephemient
07/15/2023, 1:49 PMephemient
07/16/2023, 1:43 AMModifier
instead of a custom Layout
, as long as you don't need to handle touch input