Drag-and-Drop — gerakan interaktif menyeret objek visual di layar menggunakan jari. Gerakan ini terdiri dari tiga fase: menangkap (long press atau sentuhan), memindahkan (gerakan jari dengan objek) dan melepas (menjatuhkan di zona target). Digunakan untuk mengubah urutan elemen, memindahkan file antar folder, mengatur antarmuka (drag to reorder, drag to resize). Di iOS diimplementasikan melalui UIDragInteraction, di Android melalui DragEvent dan startDragAndDrop.
Poin Utama
Drag-and-Drop (DnD, seret dan lepas) — metode manipulasi elemen grafis antarmuka di mana pengguna menangkap objek dengan jari atau mouse, memindahkannya ke posisi lain dan melepaskannya. Di antarmuka mobile, Drag-and-Drop biasanya dimulai dengan tekanan panjang (Long Press) — pengguna menahan elemen selama 300–500 ms, setelah itu sistem beralih ke mode penyeretan, dan gerakan jari memindahkan objek.
Secara historis, Drag-and-Drop muncul di antarmuka desktop (Xerox Star, 1981; Macintosh, 1984) sebagai alternatif untuk perintah salin/tempel. Di platform mobile, dukungan penuh muncul di iOS 11 (2017) dengan UIDragInteraction dan di Android 7.0 (2016) dengan Multi-Window Drag-and-Drop. Sebelumnya, penyeretan di aplikasi mobile diimplementasikan melalui solusi kustom menggunakan gesture recognizers.
Konsep kunci: drag session (sesi penyeretan), drag items (objek yang diseret), drag preview (gambaran visual objek), drop target (zona penjatuhan), drop proposal (tindakan saat menjatuhkan: pindahkan, salin, tautkan). Sistem mengelola sesi di tingkat sistem operasi, yang memungkinkan penyeretan objek antar aplikasi yang berbeda (misalnya, foto dari Galeri ke Catatan).
Drag-and-Drop dibagi menjadi tiga fase berurutan. Fase 1 — menangkap (Drag Start): pengguna memulai gerakan (biasanya Long Press), sistem membuat sesi penyeretan, menangkap data objek dan menampilkan drag preview — salinan semi-transparan dari elemen yang mengikuti jari. Dalam fase ini, sistem menolak gerakan lain (scroll, pemilihan teks) hingga DnD selesai.
Fase 2 — memindahkan (Drag Move): jari bergerak di layar, drag preview mengikuti titik sentuhan. Sistem terus menerus menentukan drop target di bawah jari dan mengirimkan peristiwa drag enter, drag move, dan drag exit. Drop target dapat bereaksi secara visual: menyala, memperluas, atau menunjukkan garis sisipan. Fase ini berlangsung dari 0,5 hingga 10+ detik tergantung pada kompleksitas tugas.
Fase 3 — melepas (Drop): jari diangkat dari layar. Sistem mengakhiri sesi penyeretan dan memanggil drop callback pada elemen target. Jika drop target menolak penjatuhan (misalnya, menyeret file ke folder tanpa hak tulis), drag preview kembali secara animasi ke posisi asli (cancel animation). Jika penjatuhan diterima, elemen menghilang dari posisi asli dan muncul di posisi target.
| Fase | Peristiwa iOS | Peristiwa Android | Status visual |
|---|---|---|---|
| Menangkap | UIDragInteractionDelegate.dragSessionWillBegin | View.OnLongClickListener → startDragAndDrop | Drag preview muncul di bawah jari |
| Memindahkan | UIDropInteractionDelegate.dragSessionDidUpdate | View.OnDragListener.onDrag (ACTION_DRAG_MOVED) | Preview bergerak, target menyala |
| Melepas | UIDropInteractionDelegate.performDrop | View.OnDragListener.onDrag (ACTION_DROP) | Animasi penjatuhan atau kembali |
Penyeretan antar aplikasi — fitur yang tersedia di kedua platform. iOS mendukung Drag-and-Drop antar aplikasi dalam mode Split View dan Slide Over (iPad). Android mendukung penyeretan antar aplikasi dalam mode Split Screen. Data ditransfer melalui UIPasteConfiguration (iOS) atau ClipData (Android). Pengembang menentukan tipe data yang didukung (UTI untuk iOS, MIME untuk Android).
UIDragInteraction — API utama iOS untuk penyeretan, ditambahkan di iOS 11. Untuk mengaktifkan penyeretan dari View, tambahkan UIDragInteraction dengan UIDragInteractionDelegate. Delegasi menentukan elemen mana yang diseret, penampilan dan perilakunya. Untuk menerima elemen digunakan UIDropInteraction dengan UIDropInteractionDelegate, yang menentukan apakah View dapat menerima penjatuhan dan bagaimana memproses data.
// UIDragInteraction — menyeret elemen dari koleksi
class DragViewController: UIViewController, UIDragInteractionDelegate {
@IBOutlet var dragSourceView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
let dragInteraction = UIDragInteraction(delegate: self)
dragSourceView.addInteraction(dragInteraction)
}
func dragInteraction(_ interaction: UIDragInteraction,
itemsForBeginning session: UIDragSession) -> [UIDragItem] {
guard let data = Data(contentsOf: selectedFileURL) else { return [] }
let itemProvider = NSItemProvider(object: data as NSData)
let dragItem = UIDragItem(itemProvider: itemProvider)
// Drag preview — salinan elemen yang diperkecil
dragItem.previewProvider = {
let previewView = UIImageView(image: thumbnailImage)
previewView.alpha = 0.8
return UIDragPreview(view: previewView)
}
return [dragItem]
}
}UIDropInteractionDelegate — antarmuka cermin untuk menerima penjatuhan. Metode canHandle(_:) memeriksa apakah tipe data didukung. sessionDidUpdate(_:) memperbarui status secara visual (penyorotan, garis sisipan). performDrop(_:) melakukan pemrosesan data akhir. iOS secara otomatis memanggil UIDropProposal dengan tipe operasi: .move (pindahkan), .copy (salin), .forbidden (dilarang). Tipe operasi memengaruhi tampilan visual (ikon + di sudut preview untuk penyalinan, tanda larangan untuk forbidden).
View.startDragAndDrop() — metode Android SDK untuk memulai penyeretan, tersedia sejak API 24 (Android 7.0). Dipanggil setelah menangkap elemen (biasanya di onLongClick). Parameter: ClipData (data), DragShadowBuilder (bayangan visual), Object myLocalState (status lokal), flags. DragShadowBuilder membuat Bitmap yang mengikuti jari. Sistem secara otomatis mengelola animasi dan peristiwa sentuhan selama penyeretan.
// Drag-and-Drop elemen RecyclerView dengan pengurutan ulang
class ReorderAdapter(private val items: MutableList<String>) :
RecyclerView.Adapter<ReorderAdapter.ViewHolder>() {
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.itemView.setOnLongClickListener {
// Membuat ClipData untuk transfer data
val clipData = ClipData.newPlainText("item", items[position])
// DragShadowBuilder kustom dengan preview diperkecil
val shadowBuilder = object : View.DragShadowBuilder(holder.itemView) {
override fun onProvideShadowMetrics(shadowSize: Point, shadowTouchPoint: Point) {
shadowSize.set(itemView.width, itemView.height / 2)
}
}
holder.itemView.startDragAndDrop(clipData, shadowBuilder, position, 0)
true
}
}
}Menerima penjatuhan di Android diimplementasikan melalui View.setOnDragListener(). Pendengar menerima peristiwa ACTION_DRAG_STARTED, ACTION_DRAG_ENTERED, ACTION_DRAG_LOCATION, ACTION_DRAG_EXITED, ACTION_DROP, ACTION_DRAG_ENDED. Dalam peristiwa ACTION_DROP, data diekstrak dari ClipData dan tindakan target dilakukan. Untuk RecyclerView dengan pengurutan ulang, direkomendasikan ItemTouchHelper.SimpleCallback — mekanisme bawaan yang secara otomatis menangani Long Press untuk menangkap, animasi pemindahan elemen, dan metode pembantu onMove/onSwiped.
Mengurutkan ulang daftar (drag to reorder) — skenario DnD paling umum: pengguna menyeret elemen daftar untuk mengubah urutannya. Contoh: menata ulang kontak favorit, menyortir tugas di tracker (Trello, Todoist), mengubah urutan lagu di playlist (Spotify, Apple Music). Diimplementasikan melalui ItemTouchHelper di Android atau UILongPressGestureRecognizer + penataan ulang sel di iOS.
Manajer file — Drag-and-Drop untuk menyalin dan memindahkan file antar folder. iOS Files App, Android Files by Google, Dropbox — semuanya mendukung DnD. Menyeret file ke folder akan memindahkannya ke dalam (move), menyeret dengan tombol Option/Ctrl ditekan akan menyalinnya (copy). Drop target menyala secara visual saat didekati, menunjukkan batas folder.
Papan Kanban — Trello, Jira, Notion menggunakan Drag-and-Drop untuk memindahkan kartu antar kolom (To Do → In Progress → Done). Saat menyeret, kartu terlepas dari kolom sumber, mengikuti jari, dan saat melewati batas kolom lain dimasukkan dengan animasi. iOS 11+ mendukung UIDragPreview dengan efek paralaks, di mana preview sedikit menyimpang dari titik sentuhan, menciptakan kedalaman.
Bagian Springboard (iOS) — menyeret ikon aplikasi di layar beranda iOS. Tekanan panjang pada ikon mengaktifkan mode “jiggling” (ikon bergetar), setelah itu pengguna dapat memindahkan ikon antar halaman dan membuat folder. Ini adalah salah satu pola UX DnD paling kompleks karena memerlukan penanganan simultan penyeretan, animasi getaran, dan pengelompokan ke dalam folder.
Umpan balik visual — sangat penting untuk Drag-and-Drop. Objek yang diseret harus berubah: mengecil (iOS: scale 0.8–0.9), menjadi semi-transparan (alpha 0.7–0.8) dan naik di atas antarmuka dengan bayangan (shadow offset). Drop target harus bereaksi secara visual saat didekati: menyala (highlight), memperluas (expand) atau menunjukkan batas (border). Tanpa sinyal ini, pengguna tidak mengerti ke mana bisa menjatuhkan objek.
Animasi kembali (drag cancel) — jika pengguna melepas elemen di luar zona penjatuhan atau di atas zona tidak valid, objek harus kembali secara animasi ke posisi asli. iOS UIDragInteractionDelegate menyediakan dragInteraction(_:sessionDidMove:) untuk pelacakan dan dragInteraction(_:session:willEndWith:) untuk animasi kembali. Android View.setOnDragListener menerima ACTION_DRAG_ENDED, di mana animasi kembali dapat dimulai melalui ValueAnimator atau ObjectAnimator.
| Rekomendasi | iOS | Android |
|---|---|---|
| Menangkap dengan gerakan | Long Press (default) | OnLongClickListener |
| Drag preview | UIDragItem.previewProvider | DragShadowBuilder |
| Umpan balik taktil | UIImpactFeedbackGenerator | HapticFeedbackConstants.LONG_PRESS |
| Animasi kembali | UIDragPreviewTarget | ViewPropertyAnimator |
| Drop proposal | UIDropProposal (.move/.copy) | ACTION_DROP + bendera |
| DnD antar aplikasi | iOS 11+ Split View (iPad) | Android 7.0+ Split Screen |
Aksesibilitas: pengguna dengan keterbatasan motorik mungkin tidak dapat melakukan gerakan menyeret. Sediakan alternatif melalui tombol “Pindahkan ke atas/bawah” untuk daftar, menu konteks “Pindahkan ke folder” untuk file. iOS VoiceOver mendukung aksi rotor “Drag” untuk memindahkan elemen. Android TalkBack menyediakan aksi kustom melalui AccessibilityNodeInfo.addAction(). Nike Run Club dan Apple Health menggunakan DnD untuk mengurutkan ulang metrik di dasbor — dengan akses melalui tombol standar.
Pertanyaan yang Sering Diajukan
Gerakan standar untuk memulai Drag-and-Drop adalah Long Press (tekanan panjang) dengan durasi 300–500 ms. iOS menggunakan mekanisme bawaan UIDragInteraction yang secara otomatis mengonversi sentuhan panjang menjadi tangkapan. Android memerlukan panggilan eksplisit startDragAndDrop() di callback OnLongClickListener. Dalam beberapa kasus (misalnya, di game), DnD dapat dimulai dengan sentuhan biasa tanpa penundaan.
Ya, Drag-and-Drop antar aplikasi didukung di iOS 11+ (iPad) dan Android 7.0+. Di iPad, penyeretan berfungsi dalam mode Split View dan Slide Over — pengguna dapat mengambil teks dari Safari dan memindahkannya ke Catatan. Di Android, DnD antar aplikasi berfungsi dalam Split Screen. Data ditransfer melalui UIPasteConfiguration (iOS) atau ClipData (Android) dengan menentukan tipe yang didukung (UTI, MIME).
Konflik DnD dan Scroll diselesaikan dengan penundaan penangkapan. Jika pengguna mulai menggerakkan jari sebelum batas waktu Long Press (500 ms) berakhir, gerakan diartikan sebagai pengguliran, bukan Drag-and-Drop. Di iOS, UIDragInteraction secara otomatis mengelola konflik ini melalui cancelsTouchesInView. Di Android, ItemTouchHelper menggunakan ambang batas — jika gerakan melebihi ambang TouchSlop, Long Press dibatalkan demi pengguliran.
Drag-and-Drop mendukung semua tipe data: teks, gambar, file, URL, objek kustom. iOS menggunakan NSItemProvider dengan tipe UTI (public.text, public.image, public.file-url). Android — ClipData dengan tipe MIME (text/plain, image/png, application/octet-stream). Untuk data kustom, dibuat ClipData.Item dengan Intent. Pada DnD antar aplikasi, data dikemas dalam format universal: plain text, HTML, RTF, UIImage/PNG.
Di iOS, animasi kembali dikelola melalui UIDragPreviewTarget — posisi akhir tempat preview kembali secara animasi. Di Android, gunakan ViewPropertyAnimator dengan translateX/translateY untuk mengembalikan elemen ke posisi asli. Durasi animasi — 200–300 ms dengan kurva easing (EaseOut). UIKit secara otomatis menambahkan UIDragPreview dengan efek paralaks yang kembali dengan mulus saat pembatalan gerakan.
Ringkasan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.
Baca juga