How to implement reordering in LazyList or LazyGrid
mainTo enable drag-and-drop reordering, follow these steps:
- Initialize State: Create a reorderable state using
rememberReorderableLazyListStateforLazyColumn/LazyRoworrememberReorderableLazyGridStateforLazyVerticalGrid/LazyHorizontalGrid. - Attach Modifier: Add the
.reorderable(state)modifier to your list or grid. - Wrap Items: Inside your
itemsblock, wrap each item's content withReorderableItem.- For keyed lists (recommended): Use
ReorderableItem(state, key = { ... }). This enables item animations. - For indexed lists: Use
ReorderableItem(state, index = { ... }).
- For keyed lists (recommended): Use
- Enable Detection: Apply either
.detectReorderAfterLongPress(state)or.detectReorder(state)to the list modifier.- Drag Handle Pattern: If you want reordering to be triggered only by a specific part of the item (a drag handle), apply the detection modifier to that specific child composable instead of the list itself.
ReorderableItem provides an isDragging boolean in its lambda, which you can use to apply visual feedback like elevation or scale during a drag.
@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)
}
}
}
}
}