Issue
The Code A is from the official sample code here.
And author told me the following content:
If you expand item number 1, you scroll away to number 20 and come back to 1, you'll notice that 1 is back to the original size.
Question 1: Why will the expand item be restored to original size after scroll forward then backward items with Code A?
Question 2: How can I keep expand item after scroll forward then backward items ?
Code A
@Composable
private fun Greetings(names: List<String> = List(1000) { "$it" } ) {
LazyColumn(modifier = Modifier.padding(vertical = 4.dp)) {
items(items = names) { name ->
Greeting(name = name)
}
}
}
@Composable
private fun Greeting(name: String) {
var expanded by remember { mutableStateOf(false) }
val extraPadding by animateDpAsState(
if (expanded) 48.dp else 0.dp
)
Surface(
color = MaterialTheme.colors.primary,
modifier = Modifier.padding(vertical = 4.dp, horizontal = 8.dp)
) {
Row(modifier = Modifier.padding(24.dp)) {
Column(modifier = Modifier
.weight(1f)
.padding(bottom = extraPadding)
) {
Text(text = "Hello, ")
Text(text = name)
}
OutlinedButton(
onClick = { expanded = !expanded }
) {
Text(if (expanded) "Show less" else "Show more")
}
}
}
}
Added Content
Question 3: If I use Code B, I find the expand items can be kept after I scroll forward then backward items. why ?
Code B
@Composable
private fun Greetings(names: List<String> = List(50) { "$it" } ) {
Column(
modifier = Modifier.fillMaxSize().verticalScroll(rememberScrollState())
)
{
for (name in names) {
Greeting(name = name)
}
}
}
...
Again:
I rewrite Code C by jVCODE's suggestion, it works, the expand items can be kept after I scroll forward then backward items after I replace var expanded by remember { mutableStateOf(false) } with var expanded by rememberSaveable { mutableStateOf(false) }.
According to Arpit Shukla's view point:
When you scroll in LazyColumn, the composables that are no longer visible get removed from the composition tree and when you scroll back to them, they are composed again from scratch. That is why expanded is initialized to false again.
In my mind, the rememberSaveable will only be available when I rotate screen.
So I think var expanded by rememberSaveable { mutableStateOf(false) } will be relaunched and assigned as false when I scroll forward then backward items, and the expand items will be restored to original size. But in fact the expand items can be kept after I scroll forward then backward items.
Question 4: Why can rememberSaveable work well in this scenarios?
Code C
@Composable
private fun Greetings(names: List<String> = List(1000) { "$it" } ) {
LazyColumn(modifier = Modifier.padding(vertical = 4.dp)) {
items(items = names) { name ->
Greeting(name = name)
}
}
}
@Composable
private fun Greeting(name: String) {
var expanded by rememberSaveable { mutableStateOf(false) }
...
}
Solution
var expanded by remember { mutableStateOf(false) }
This expanded state is local to the Greeting composable. When you scroll in LazyColumn, the composables that are no longer visible get removed from the composition tree and when you scroll back to them, they are composed again from scratch. That is why expanded is initialized to false again.
If you want to preserve the expanded state, you should hoist this state in a different state holder (for example in the list where you store the names, also store the expanded state of the Greeting with that name). And if you also want this to survive configuration changes you should hoist this state from a ViewModel.
You can also use rememberSaveable to save the expanded state but if you have a very large list, you will end up saving a lot of data in the bundle. So I would suggest avoid using rememberSaveable inside a LazyColumn.
Answered By - Arpit Shukla
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.