Compose版本1.2.1 ,目前官方的Jetpack Compose 暂时还不支持LazyList的拖动排序,这里我们使用第三方开源库ComposeReorderable
dependencies {
implementation("org.burnoutcrew.composereorderable:reorderable:<latest_version>")
}
这里我们用最新的版本0.9.2
1.长按触发拖动排序
这里就直接用ComposeReorderable官方的栗子就好了,用的是modifier.detectReorderAfterLongPress(state)
@Composable
fun VerticalReorderList() {
val data = remember { mutableStateOf(List(100) { "Item $it" }) }
val state = rememberReorderableLazyListState(onMove = { from, to ->
data.value = data.value.toMutableList().apply {
add(to.index, removeAt(from.index))
}
})
LazyColumn(
state = state.listState,
modifier = Modifier
.reorderable(state)
.detectReorderAfterLongPress(state)
) {
items(data.value, { it }) { item ->
ReorderableItem(state, key = item) { isDragging ->
val elevation = animateDpAsState(if (isDragging) 16.dp else 0.dp)
Column(
modifier = Modifier
.shadow(elevation.value)
.background(MaterialTheme.colors.surface)
) {
Text(item,modifier = Modifier
.fillMaxWidth()
.height(45.dp))
}
}
}
}
}
2.拖动右侧Icon进行拖动排序,如顶图
用modifier = Modifier.detectReorder(state)
@Composable
fun DragListDemo() {
Scaffold(topBar = { CenterTopAppBar(title = "拖动排序") }) { paddingValues ->
Column(Modifier.padding(paddingValues)) {
val data =
remember { mutableStateOf(List(100) { "Item $it" }) }
val state = rememberReorderableLazyListState(onMove = { from, to ->
data.value = data.value.toMutableList().apply {
add(to.index, removeAt(from.index))
}
})
LazyColumn(
state = state.listState,
modifier = Modifier
.reorderable(state)
) {
itemsIndexed(items = data.value, key = { _, it -> it }) { index, item ->
ReorderableItem(state, key = item) { isDragging ->
val elevation = animateDpAsState(if (isDragging) 16.dp else 0.dp)
Row(
modifier = Modifier
.fillMaxWidth()
.height(45.dp)
.shadow(elevation.value)
.background(MaterialTheme.colors.surface)
.padding(horizontal = 15.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text(item)
Icon(
imageVector = Icons.Rounded.Menu,
contentDescription = "",
modifier = Modifier.detectReorder(state)
)
}
}
}
}
}
}
}
3. 当list超过一页,拖动一下item,LazyColumn就会自动滑动到最后一页的问题。
记录一下我碰到的这问题, 为了让这个dargList compose 可以重用,就简单的把它拆分了一下:
@Composable
fun DragListDemo() {
Scaffold(topBar = { CenterTopAppBar(title = "拖动排序") }) { paddingValues ->
Column(Modifier.padding(paddingValues)) {
val data =
remember { mutableStateOf(List(100) { "Item $it" }) }
val state = rememberReorderableLazyListState(onMove = { from, to ->
data.value = data.value.toMutableList().apply {
add(to.index, removeAt(from.index))
}
})
DragListContent(state,data.value)
}
}
}
dragList 和数据源解耦
@Composable
fun DragListContent(state: ReorderableLazyListState, list: List<String>) {
LazyColumn(
state = state.listState,
modifier = Modifier
.reorderable(state)
) {
items(items = list, key = { it }) { item ->
ReorderableItem(state, key = item) { isDragging ->
val elevation = animateDpAsState(if (isDragging) 16.dp else 0.dp)
Row(
modifier = Modifier
.fillMaxWidth()
.height(45.dp)
.shadow(elevation.value)
.background(MaterialTheme.colors.surface)
.padding(horizontal = 15.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text(item)
Icon(
imageVector = Icons.Rounded.Menu,
contentDescription = "",
modifier = Modifier.detectReorder(state)
)
}
}
}
}
}
然后运行,结果如图:
可以看到,item只拖动了一点点距离,lazyColumn就自动滑动到最后一页了。
然后又把它还原回去,把lazyColumn和数据放一起,结果就好了没有这个问题了。
那一定要把数据和lazyColumn拆开怎么办:
解决方案一
用State<List> 做参数,因为State是稳定类型的,而List不是稳定类型的。
@Composable
fun DragListContent(state: ReorderableLazyListState, list: State<List<String>>) {
LazyColumn(
state = state.listState,
modifier = Modifier
.reorderable(state)
) {
items(items = list.value, key = { it }) { item ->
ReorderableItem(state, key = item) { isDragging ->
val elevation = animateDpAsState(if (isDragging) 16.dp else 0.dp)
Row(
modifier = Modifier
.fillMaxWidth()
.height(45.dp)
.shadow(elevation.value)
.background(MaterialTheme.colors.surface)
.padding(horizontal = 15.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text(item)
Icon(
imageVector = Icons.Rounded.Menu,
contentDescription = "",
modifier = Modifier.detectReorder(state)
)
}
}
}
}
}
那不用State一定要用list做参数呢
解决方案二
用SnapshotStateList
@Composable
fun DragListDemo() {
Scaffold(topBar = { CenterTopAppBar(title = "拖动排序") }) { paddingValues ->
Column(Modifier.padding(paddingValues)) {
val data =
remember { List(100) { "Item $it" }.toMutableStateList() }
val state = rememberReorderableLazyListState(onMove = { from, to ->
data.apply {
add(to.index, removeAt(from.index))
}
})
DragListContent(state,data)
}
}
}