.onMove drag and drop

Hi everyone,

I’m working on a SwiftUI project where I want the entire page to be scrollable. Within this page, I have a bottom section that displays a list of items, and these items are being rendered from a SwiftData model object. My main goal is to make this list reorderable using the onMove method.

The challenge I’m facing is that using a List inside a ScrollView requires a fixed height for the List, which doesn’t work for my use case because the content is dynamic and the height can vary. Since I’m using SwiftData to manage my data, I need a way to keep this list fully dynamic.

I’m open to using a VStack instead of a List to display the items, but I still need the reorder functionality that List provides. Does anyone know a good way to achieve this behavior? Is there a way to use onMove or similar functionality without needing a fixed height, or perhaps an alternative approach that might work better with SwiftData?

Any suggestions or insights would be greatly appreciated!

Thanks!

Answered by DTS Engineer in 802102022

A List is also Scrollable, so you wouldn't want to have that in a ScrollView.

Using a VStack + ScrollView is teh right way to go. You could implement the reorder functionality by implementing a drag and drop operation using draggable(_:) and dropDestination(for:action:isTargeted:) modifiers.

You could have a look the following to learn more about drag and drop in SwiftUI.

A List is also Scrollable, so you wouldn't want to have that in a ScrollView.

Using a VStack + ScrollView is teh right way to go. You could implement the reorder functionality by implementing a drag and drop operation using draggable(_:) and dropDestination(for:action:isTargeted:) modifiers.

You could have a look the following to learn more about drag and drop in SwiftUI.

But draggable and dropDestination does not seem to support multi drag and drop.

This is a valid use case often dismissed. I use two types of solutions to a ScrollView dynamically adjusting to a List inside it:

If your List rows have a fixed known height, something like this should work dynamically: ScrollView{ VStack{ List{} } .frame(height: CGFloat(listRows.count*30) }

If your list rows have unpredictable sizes, a not elegant but functional workaround is to put your List inside a ZStack along with an overlaying zero opacity ForEach with Texts (as an example) that have the size of each respectI’ve row. The ScrollView will dynamically adapt to the size of the transparent Texts.

.onMove drag and drop
 
 
Q