背景
在上一篇文章中,我介绍了一个自己写的Compose划动组件。它可以向左或向右滑动以显示操作按钮并支持自定义设计操作按钮。它还提供了封装好的文字和
按钮组件:SwipeIcon 和 SwipeText,用于通用操作按钮。
该组件最常用的使用场景就是在列表中组合使用。但是这就要求某个已经划开的组件在列表发生滚动或其他item被划开时,需要自动恢复原样。否则的话会出现多个列表项都处于展开状态的情况,用户体验不好。而这个组件在设计的时候就考虑到了这种情况并提供了解决方案。这篇文章我们将介绍如何在列表中支持该能力。
状态创建
首先,我们需要定义一个SwipeableState来保存当前打开的列表项的划动状态,方便我们后续将其归位
var currentSwipeState: SwipeableState<Int>? by remember {
mutableStateOf(null)
}
更新状态
然后,我们需要定义一个回调并传递给SwipeBox组件,用来更新当前展开的列表项及处理列表项之间的互斥逻辑
val onSwipeStateChanged = { state : SwipeableState<Int> ->/** * if it is swiping back and it equals to the current state * it means that the current open box is closed, then we set the state to null */if (state.targetValue == 0 && currentSwipeState == state) {
currentSwipeState = null
}
// if there is no opening box, we set it to this opening oneelse if (currentSwipeState == null) {
currentSwipeState = state
} else {
// there already had one box opening, we need to swipe it back and then update the state to new one
coroutineScope.launch {
currentSwipeState!!.animateTo(0)
currentSwipeState = state
}
}
}
SwipeBox(onSwipeStateChanged){ state, _, _ ->// callback on parent when the state targetValue changes which means it is swiping to another state.LaunchedEffect(state.targetValue) {
onSwipeStateChanged(state)
}
}
可以看到,我们在每次划动状态发生改变时,都将之前已经展开的item复位,并更新最新的状态,用于下一次归位使用。
拦截滚动
最后,我们需要定义一个nestedScrollConnection用来拦截列表的滚动,这样我们就能在滚动时将展开的列表项复位
val nestedScrollConnection = remember {
object : NestedScrollConnection {
/** * we need to intercept the scroll event and check whether there is an open box * if so ,then we need to swipe that box back and reset the state */
override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
if (currentSwipeState != null && currentSwipeState!!.currentValue != 0) {
coroutineScope.launch {
currentSwipeState!!.animateTo(0)
currentSwipeState = null
}
}
return Offset.Zero
}
}
}
LazyColumn(
modifier = Modifier
.nestedScroll(nestedScrollConnection)
)
这里我们创建了一个nestedScrollConnection来拦截列表滚动,它会感知到列表滚动事件,并将当前展开的划动组件归位。这样就可以保证列表划动时不会有展开的划动组件。
总结
完成这三步后,我们就实现了划动组件在列表中自动复位的能力了。完整示例可以参考:https://github.com/KevinnZou/compose-swipeBox/blob/main/app/src/main/java/com/kevinnzou/compose/composeswipebox/SwipeBoxList.kt