Using UIDragPreview to Customize Drag Items
This post is brought to you by Emerge Tools, the best way to build on mobile.
let concatenatedThoughts = """
Welcome to Snips! Here, you'll find a short, fully code complete sample with two parts. The first is the entire code sample which you can copy and paste right into Xcode. The second is a step by step explanation. Enjoy!
"""
The Scenario
Change how your dragged items appear during an active drag.
Note:This snip assumes you’ve already set up drag and drop reordering, which you can get a full code sample for here.
extension PreviewParametersViewController: UITableViewDragDelegate {
// 1
func tableView(_ tableView: UITableView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
guard let item = datasource.itemIdentifier(for: indexPath) else {
return []
}
let itemProvider = NSItemProvider(object: item.id.uuidString as NSString)
let dragItem = UIDragItem(itemProvider: itemProvider)
dragItem.localObject = item
// 2
guard let cell = tableView.cellForRow(at: indexPath) else { return [dragItem] }
let cellInsetContents = cell.contentView.bounds.insetBy(dx: 2.0, dy: 2.0)
// 3
dragItem.previewProvider = {
// 4
let dragPreviewParams = UIDragPreviewParameters()
dragPreviewParams.visiblePath = UIBezierPath(roundedRect:cellInsetContents, cornerRadius: 8.0)
// 5
return UIDragPreview(view: cell.contentView, parameters: dragPreviewParams)
}
return [dragItem]
}
}
Now, when you drag to reorder you’ll see we get a nice, rounded view of the cell that’s being dragged instead of the default square edges:
The Breakdown
Step 1
Both UICollectionView
and UITableView
have protocol methods that look similar for returning drag items, i.e. itemsForBeginning...
. The one for table view is this one:
func tableView(_ tableView: UITableView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem]
Here’s where we can customize dragged views.
Step 2
Since we want to base our customized drag preview off of the cell contents itself, first we make sure that we can get a reference to it. This is important because of cell recycling. For example, the one we’re after might already be offscreen if the user scrolled up or down beyond it.
Step 3
Each UIDragItem
has a previewProvider
closure that allows us to return a UIDragPreview
instance. This last object allows us to customize the dragged item.
Step 4
Using the visiblePath
property of UIDragPreviewParameters
, we can give it a UIBezierPath
based off of the cell’s content frame, shrunk down a bit and with a rounded corner. Preview parameters work together with a drag preview to determine how the drag will look.
Step 5
Finally, we return the UIDragPreview
that uses our UIDragPreviewParameters
from the closure and we’re good to go!
Until next time ✌️