Reorderable list
Rows dragged into a new order, the rest sliding out of the way: what a queue is rearranged with.
Desktop
arkui::reorder


A press that moves less than reorder::THRESHOLD is a click; past it the row lifts, and the rows it passes slide a row's height out of its way on reorder::SLIDING, a spring.
arkui::reorder
A list whose rows are dragged into a new order: the row lifts and follows the pointer, and the rows it passes slide out of its way.
Reorder::press(from, rows, row, y, now)drag(y, now), drop(now) -> Drop::{Click, Moved { from, to, settle }}list(rows, row, drag, settle, now)moved(items, from, to)THRESHOLD, SLIDING (spring 1.0, 0.3 s), SETTLING (spring 0.85, 0.3 s, from the pointer's speed)
Rules
- Under THRESHOLD pixels a press is a click, so a row still does what a click on it did.
- Where a row lands is arithmetic on how far the pointer moved, the rows being one height: nothing laid out is measured.
- The app owns the order: it moves its row on a drop, and draws the new order with the Settle until its own order says so.
Mobile
Where
ui/Reorder.kt: rememberReorder, ReorderableItem
How
- A LazyColumn drawn in reorder.order(items, key), each row in ReorderableItem(reorder, key, keys): a long press lifts it, and onMove(from, to) is told on the drop.
- The rows that make way are the list's own animateItem on Springs.MOVE; a tap still does what a tap did.
- In sections, rememberReorder(list, lead, isHeader) { key, landing -> … }: a row dragged past a header changes section, a header held folds every section to its header and moves its own, and the drop is told as Landing(section, before).
Where
swift/ArkUI: Reorderable, ReorderHandle
How
- Reorderable(items, key:, onMove:) { item, handle in … }: the row places the handle it is given, and is dragged by it, as the Music app's queue is.
- The rows that make way move on Springs.move; the row keeps its tap and its context menu.