I have a Custom Composable Calendar
, here
I try to add a functionality to switch between month view and week view.
The point of the code is below:
LazyRow {
items(
key = { page -> state.getKey(page) },
) { page ->
monthFiled(
date = state.getDateByPage(page),
)
}
}
And here is the point:
- In monthView mode,
state.getKey(page)
return a key likesYearMonth
(or page or else). - In week mode,
state.getKey(page)
return a key likesyear_weeks
(or page or else).
They are different.
To ensure that the animation works correctly, I want the keys for the month view and the week view to be consistent when switching between them.
However, the relationship between month and week views is not one-to-one but one-to-many (1:5).
Is there anything that can help me switch between month and week views, as well as switch back and forth between month and week views smoothly?
Here is my minimal reproducible example
private interface View {
val count: Int
fun key(index: Int): Any
fun content(index: Int): List<Int>
}
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun MainScreen(innerPadding: PaddingValues) {
val list = listOf(0, 1, 2, 3, 4, 5)
// expand
val view1 = object : View {
override val count: Int get() = list.size / 3
override fun key(index: Int) = list[index * 3]
override fun content(index: Int) = list.subList(index * 3, (index + 1) * 3)
}
// collapse
val view2 = object : View {
override val count: Int get() = list.size
override fun key(index: Int) = list[index]
override fun content(index: Int) = list.subList(index / 3 * 3, (index / 3 + 1) * 3)
}
var view: View by remember { mutableStateOf(view1) }
val state = rememberLazyListState()
LazyColumn(
modifier = Modifier
.height(100.dp)
.clickable { view = if (view == view1) view2 else view1 },
state = state,
flingBehavior = rememberSnapFlingBehavior(state)
) {
items(
count = view.count,
key = view::key,
) { index ->
Row(
modifier = Modifier.fillParentMaxHeight(),
) {
view.content(index).forEach { item ->
AnimatedVisibility(visible = view == view1 || view.key(index) == item) {
Text(
"$item",
modifier = Modifier
.width(100.dp)
.fillMaxHeight()
.border(1.dp, Purple80),
)
}
}
}
}
}
}
It displays the list in two different ways: view1 and view2.
- One way is to display 3 items per row,
- and the other way is to display 1 item per row.
Due to key reuse,
an animation can be achieved between element0 and element0~2 for expanding and collapsing.
However, an animation cannot be achieved between element1 and element0~2.
Do you have any good suggestions?
Update at 2024/6/13
As you can see:
- view1 (0,1,2) key is 0.
- view2 (0) key is 0.
them can animate good.
In other index, the animation is wrong.(maybe contains other problems.)
I need to find a way to animate good between view1
to view2
.
minimal reproducible example
.