我有一个
Custom Composable Calendar
,这里
我尝试添加一个在月视图和周视图之间切换的功能。
代码要点如下:
LazyRow {
items(
key = { page -> state.getKey(page) },
) { page ->
monthFiled(
date = state.getDateByPage(page),
)
}
}
重点是:
state.getKey(page)
返回类似YearMonth
的键(或页面或其他)。state.getKey(page)
返回喜欢year_weeks
的键(或页面或其他)。他们是不同的。
为了确保动画正常工作,我希望月视图和周视图之间切换时的按键保持一致。
但是,月视图和周视图之间的关系不是一对一,而是一对多(1:5)。
有什么可以帮助我在月视图和周视图之间切换,以及在月视图和周视图之间平滑地来回切换吗?
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),
)
}
}
}
}
}
}
它以两种不同的方式显示列表:view1 和 view2。
由于密钥重复使用,
element0和element0~2之间可以实现展开和折叠的动画。
但是element1和element0~2之间无法实现动画。
您有什么好的建议吗?
这些键没有帮助,因为您只能将 view1 的键映射到 view2,而不能将 view1 的键映射到 view2。
在切换视图后,忘记按键并使用
LazyListState
的 requestScrollToItem
来调整滚动位置:
.clickable {
view = if (view == view1) {
state.requestScrollToItem(state.firstVisibleItemIndex * 3)
view2
} else {
state.requestScrollToItem(state.firstVisibleItemIndex / 3)
view1
}
},
现在切换视图时不再需要
items
' key
参数。如果您不需要钥匙做其他事情,您可以将它们完全删除。