Drag-and-Drop Implementation for Mobile Apps
We, as mobile developers, know: dragging elements looks like a simple animation, but it hides complex coordination—gesture detection, visual copy, hit-testing drop zones, model updates, and return animation. Each step is a potential bug. Our team has 5+ years of experience implementing drag-and-drop on iOS, Android, and Flutter. We have solved dozens of issues with cell indexing, auto-scroll, and haptic feedback. We offer turnkey implementation: from design to store publication. Order development—get a stable solution with a 6-month warranty.
Comparison of Implementation Across Platforms
| Platform | API / Library | Complexity | Dev Time (simple reorder) |
|---|---|---|---|
| iOS (UIKit) | UIDragInteraction, UIDropInteraction | Medium | 2–3 days |
| iOS (SwiftUI) | .draggable(), .dropDestination() | Low | 1–2 days |
| Android (View) | startDragAndDrop(), setOnDragListener() | Medium | 2–4 days |
| Android (Compose) | Modifier.dragAndDropSource(), dragAndDropTarget() | Medium | 2–3 days |
| Flutter | Draggable, DragTarget, ReorderableListView | Medium | 3–5 days |
Native implementation on iOS using UIDragInteraction is 2x faster than a custom Flutter solution when working with large lists.
iOS: UIKit and SwiftUI
Since iOS 11, Apple provides a built-in Drag & Drop API via UIDragInteraction and UIDropInteraction. UIDragInteraction is added to the source view, UIDropInteraction to the target view. Data is transferred through NSItemProvider—a universal container for any data type.
let dragInteraction = UIDragInteraction(delegate: self) view.addInteraction(dragInteraction) The key delegate method dragInteraction(_:itemsForBeginning:) must return [UIDragItem] with NSItemProvider. For internal drag & drop, you can pass any object via localObject—it is not serialized and is available instantly.
For UICollectionView and UITableView, there are specialized delegates with methods like collectionView(_:itemsForBeginningDragSession:at:). Built-in reorder support through collectionView(_:moveItemAt:to:)—no need to manually manage animation.
Problems with UICollectionView drag. When dragging, the collection automatically creates a snapshot of the cell. If the cell contains AVPlayerLayer or custom CALayer animations, the snapshot looks frozen. Solution: override dragPreviewParametersForItemAt: and return UIDragPreviewParameters with a custom visiblePath.
In SwiftUI—.draggable() and .dropDestination() since iOS 16. Data must conform to the Transferable protocol. For custom types, implement Transferable via CodableRepresentation or DataRepresentation. This reduces code volume by 30% compared to UIKit.
Android: View and Compose
On Android, View.startDragAndDrop() (API 24+). DragShadowBuilder creates a shadow—override onDrawShadow() for a custom appearance. View.setOnDragListener() on the target handles events: ACTION_DRAG_ENTERED, ACTION_DRAG_EXITED, ACTION_DROP, ACTION_DRAG_ENDED.
In Jetpack Compose—Modifier.dragAndDropSource {} and Modifier.dragAndDropTarget {} since Compose 1.5. DragAndDropTransferData with ClipData as a container. For reorder inside LazyColumn, use the compose-reorderable library.
Flutter: Widgets and Reorder
Flutter offers Draggable<T> and DragTarget<T>. Draggable creates childWhenDragging (placeholder) and feedback (widget under the finger). DragTarget.onWillAcceptWithDetails() for validation, onAcceptWithDetails() for handling.
For list reordering, use ReorderableListView. onReorder receives oldIndex and newIndex. Important bug: when newIndex > oldIndex, subtract 1 before list.insert(). The documentation mentions this, but developers often miss it.
How to Ensure Auto-Scroll During Drag?
When the user drags an element to the edge of the list, the list should scroll. In UIKit—UIScrollView auto-scroll triggers when within 50pt of the edge. In Flutter—combine DragTarget with ScrollController.animateTo() on onWillAccept when the cursor is within 80px of the edge. This is standard practice but requires precise tuning.
Why Is Haptic Feedback Important During Drag?
Haptic feedback at the start of the drag gives the user a sense of "grasping" the object. On iOS, use UIFeedbackGenerator.impactOccurred() when longPressGestureRecognizer.state == .began. Without haptic feedback, drag feels "weightless," degrading UX. On Android—HapticFeedbackConstants.LONG_PRESS.
Common Problems and Solutions
| Problem | Solution | Platform |
|---|---|---|
| Snapshot frozen | Override dragPreviewParameters | iOS |
| Index drift during fast drag | Update dataSource synchronously with animation | All |
| No auto-scroll | Add edge proximity detection and scrolling | iOS, Flutter |
| Cancel without animation | Use onDraggableCanceled() with Velocity | Flutter |
Model Data State
When reordering, update the dataSource synchronously with the animation, not after. Otherwise, fast consecutive drags cause index drift. This is a common mistake leading to bugs.
What’s Included in Drag-and-Drop Implementation
- UX analysis and prototyping (if needed)
- Native or cross-platform API integration
- Custom animation and haptic feedback
- Auto-scroll handling and cancel animation
- Testing on real devices (iOS/Android)
- Integration documentation and 1-month support
- App Store or Google Play submission (optional)
How to Implement Drag-and-Drop on iOS: Step-by-Step
- Add
UIDragInteractionto the source view and implement the delegate. - Add
UIDropInteractionto the target view and implement the delegate. - Configure
NSItemProviderfor data transfer. - Handle
sessionDidUpdatefor visual feedback. - Implement cancel return animation (default is present).
Timelines and Cost
Timelines depend on complexity: simple list reorder—2–3 days, system with multiple zones and animations—5–7 days. Cost is calculated individually. Our company has completed 30+ projects with drag-and-drop. Get a consultation—we estimate your project in 1 day.
Quality Guarantee
We guarantee stable functionality on all target devices. We provide a conformity certificate (if required). Contact us—we implement drag-and-drop turnkey.







