Drag-and-Drop — ماهیت، Drag and Drop در برنامه‌های موبایل

نویسنده: IT Sectr منتشر شده: 2026-02-27 زمان مطالعه: 9 دقیقه

Drag-and-Drop — یک حرکت انتراکتیوی کشیدن شیئه مرئی با انگشت بر روی صفحه نمایش است. این حرکت از سه مرحله تشکیل شده: گیرفتاری (long press یا لمس)، جابجایی (حرکت انگشت با شیء) و رها کردن (انداختن در منطقه مقصد). برای تغییر ترتیب عناصر، انتقال فایل‌ها بین پوشه‌ها، سازماندهی رابط (drag to reorder, drag to resize) استفاده می‌شود. در iOS از طریق UIDragInteraction و در Android از طریق DragEvent و startDragAndDrop پیاده سازی می‌شود.

نکات کلیدی

  • سه مرحله — Drag-and-Drop شامل گیرفتاری، جابجایی و رها کردن شیء است
  • UIDragInteraction — کلاس اصلی iOS برای شروع و پردازش کشیدن
  • startDragAndDrop — روش Android View برای شروع کشیدن پس از گیرفتاری
  • Drag shadow — سایه مرئی شیئه کشیده شده که انگشت را دنبال می‌کند
  • Drop target — منطقه رهایش که با نزدیک شدن شیء کشیده شده روشن می‌شود

Drag-and-Drop چیست؟

Drag-and-Drop (DnD، کشیدن و رها کردن) — روشی برای مانیپولاسیون عناصر گرافیکی رابط است که در آن کاربر شیءی را با انگشت یا ماوس گرفته، آن را به مکانی دیگر منتقل کرده و رها می‌کند. در رابط‌های موبایل، Drag-and-Drop معمولاً با فشار دراز (Long Press) آغاز می‌شود — کاربر عنصری را به مدت 300–500 میلی‌ثانیه نگه می‌دارد، سپس سیستم رابط را به حالت کشیدن تغییر می‌دهد و حرکت انگشت شیء را دنبال می‌کند.

از نظر تاریخی، Drag-and-Drop اولین بار در رابط‌های رومیزی (Xerox Star، 1981؛ Macintosh، 1984) به عنوان جایگزینی برای دستورات کپی/چسباندن ظاهر شد. در پلتفرم‌های موبایل، پشتیبانی کامل در iOS 11 (2017) با UIDragInteraction و در Android 7.0 (2016) با Multi-Window Drag-and-Drop ارائه شد. قبل از آن، کشیدن و رها کردن در برنامه‌های موبایل از طریق راه‌حل‌های سفارشی با gesture recognizers پیاده سازی می‌شد.

مفاهیم کلیدی: drag session (جلسه کشیدن)، drag items (اشیاء کشیده شده)، drag preview (تصویر مرئی شیء)، drop target (منطقه رهایش)، drop proposal (عمل در زمان رهایش: انتقال، کپی، اتصال). سیستم جلسه را در سطح سیستم‌عامل مدیریت می‌کند که امکان کشیدن اشیاء را بین برنامه‌های مختلف فراهم می‌کند (مثلاً، عکس از گالری به یادداشت‌ها).

مراحل Drag-and-Drop

Drag-and-Drop به سه مرحله پیاپی تقسیم می‌شود. مرحله 1 — گیرفتاری (Drag Start): کاربر حرکت را آغاز می‌کند (معمولاً Long Press)، سیستم یک جلسه کشیدن ایجاد می‌کند، داده‌های شیء را ضبط می‌کند و drag preview — یک کپی نیمه شفاف از عنصر که انگشت را دنبال می‌کند را نمایش می‌دهد. در این مرحله، سیستم تا پایان DnD سایر حرکات (پیمایش، انتخاب متن) را رد می‌کند.

مرحله 2 — جابجایی (Drag Move): انگشت بر روی صفحه حرکت می‌کند، drag preview نقطه لمس را دنبال می‌کند. سیستم به طور مداوم drop target زیر انگشت را تعیین کرده و رویدادهای drag enter، drag move و drag exit را ارسال می‌کند. Drop target می‌تواند به صورت بصری واکنش نشان دهد: روشن شود، گسترش یابد یا خط درج نشان دهد. این مرحله بسته به پیچیدگی کار از 0.5 تا 10+ ثانیه طول می‌کشد.

مرحله 3 — رها کردن (Drop): انگشت از صفحه جدا می‌شود. سیستم جلسه کشیدن را پایان می‌دهد و در عنصر هدف، drop callback را فراخوان می‌کند. اگر drop target رهایش را رد کند (مثلاً، کشیدن فایل به پوشه‌ای بدون مجوز نوشتن)، drag preview با انیمیشن به مکان اصلی خود باز می‌گردد (cancel animation). اگر رهایش پذیرفته شود، عنصر از مکان اصلی ناپدید شده و در مکان مقصد ظاهر می‌شود.

مرحلهرویداد iOSرویداد Androidوضعیت بصری
گیرفتاریUIDragInteractionDelegate.dragSessionWillBeginView.OnLongClickListener → startDragAndDropDrag preview زیر انگشت ظاهر می‌شود
جابجاییUIDropInteractionDelegate.dragSessionDidUpdateView.OnDragListener.onDrag (ACTION_DRAG_MOVED)Preview حرکت می‌کند، target روشن می‌شود
رها کردنUIDropInteractionDelegate.performDropView.OnDragListener.onDrag (ACTION_DROP)انیمیشن رهایش یا بازگشت

کشیدن بین برنامه‌ای — قابلیتی که در هر دو پلتفرم موجود است. iOS از Drag-and-Drop بین برنامه‌ها در حالت Split View و Slide Over (iPad) پشتیبانی می‌کند. Android از کشیدن بین برنامه‌ها در حالت Split Screen پشتیبانی می‌کند. داده‌ها از طریق UIPasteConfiguration (iOS) یا ClipData (Android) با مشخص کردن نوع‌های پشتیبانی شده (UTI برای iOS، MIME برای Android) انتقال می‌یابند.

Drag-and-Drop در iOS: UIDragInteraction

UIDragInteraction — API اصلی iOS برای کشیدن، اضافه شده در iOS 11. برای فعال کردن کشیدن از View، UIDragInteraction را با UIDragInteractionDelegate اضافه کنید. دلگات مشخص می‌کند که کدام عناصر کشیده می‌شوند، ظاهر و رفتار آنها. برای پذیرش عناصر از UIDropInteraction با UIDropInteractionDelegate استفاده می‌شود که مشخص می‌کند آیا View می‌تواند رهایش را بپذیرد و چگونه داده‌ها را پردازش کند.

swift
// UIDragInteraction — کشیدن عنصر از کلکشن
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 — نسخه کوچک‌شده عنصر
        dragItem.previewProvider = {
            let previewView = UIImageView(image: thumbnailImage)
            previewView.alpha = 0.8
            return UIDragPreview(view: previewView)
        }
        return [dragItem]
    }
}

UIDropInteractionDelegate — رابط آیینه‌ای برای پذیرش رهایش. روش canHandle(_:) بررسی می‌کند که آیا نوع داده پشتیبانی می‌شود. sessionDidUpdate(_:) وضعیت را به صورت بصری به‌روز می‌کند (روشنایی، خط درج). performDrop(_:) پردازش نهایی داده‌ها را انجام می‌دهد. iOS به طور آتوماتیک UIDropProposal را با نوع عملیات فراخوان می‌کند: .move (انتقال)، .copy (کپی)، .forbidden (ممنوع). نوع عملیات بر نمایش بصری تأثیر می‌گذارد (آیکون + در گوشه preview برای کپی، علامت ممنوعیت برای forbidden).

Drag-and-Drop در Android: startDragAndDrop

View.startDragAndDrop() — روش Android SDK برای شروع کشیدن، موجود از API 24 (Android 7.0). پس از گیرفتاری عنصر (معمولاً در onLongClick) فراخوان می‌شود. پارامترها: ClipData (داده)، DragShadowBuilder (سایه بصری)، Object myLocalState (وضعیت محلی)، flags. DragShadowBuilder یک Bitmap ایجاد می‌کند که انگشت را دنبال می‌کند. سیستم به طور آتوماتیک انیمیشن و رویدادهای لمسی را در طول کشیدن مدیریت می‌کند.

kotlin
// Drag-and-Drop عنصر RecyclerView با تغییر ترتیب
class ReorderAdapter(private val items: MutableList<String>) :
    RecyclerView.Adapter<ReorderAdapter.ViewHolder>() {

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.itemView.setOnLongClickListener {
            // ClipData برای انتقال داده ایجاد می‌کنیم
            val clipData = ClipData.newPlainText("item", items[position])

            // DragShadowBuilder سفارشی با preview کوچک‌شده
            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
        }
    }
}

پذیرش رهایش در Android از طریق View.setOnDragListener() انجام می‌شود. گوش‌کن رویدادهای ACTION_DRAG_STARTED، ACTION_DRAG_ENTERED، ACTION_DRAG_LOCATION، ACTION_DRAG_EXITED، ACTION_DROP، ACTION_DRAG_ENDED را دریافت می‌کند. در رویداد ACTION_DROP، داده‌ها از ClipData استخراج شده و عمل هدف انجام می‌شود. برای RecyclerView با تغییر ترتیب، ItemTouchHelper.SimpleCallback توصیه می‌شود — مکانیسم ساخته شده که به طور آتوماتیک Long Press را برای گیرفتاری، انیمیشن جابجایی عناصر و روش‌های کمکی onMove/onSwiped را پردازش می‌کند.

سناریوهای کاربرد Drag-and-Drop

تغییر ترتیب لیست‌ها (drag to reorder) — رایج‌ترین سناریوی DnD: کاربر عناصر لیست را برای تغییر ترتیب آنها کشیده و رها می‌کند. نمونه‌ها: جابجایی مخاطبان در لیست علاقه‌مندی‌ها، مرتب سازی وظایف در ریگباب‌های پیگیری (Trello، Todoist)، تغییر ترتیب آهنگ‌ها در لیست پخش (Spotify، Apple Music). از طریق ItemTouchHelper در Android یا UILongPressGestureRecognizer + جابجایی سلول‌ها در iOS پیاده سازی می‌شود.

مدیران فایل — Drag-and-Drop برای کپی و انتقال فایل‌ها بین پوشه‌ها. iOS Files App، Android Files by Google، Dropbox — همه DnD را پشتیبانی می‌کنند. کشیدن فایل روی پوشه آن را به داخل منتقل می‌کند (move)، کشیدن با کلید Option/Ctrl کپی می‌کند (copy). Drop target در حال نزدیک شدن به صورت بصری روشن شده و مرزهای پوشه را نشان می‌دهد.

تخته‌های کانبان — Trello، Jira، Notion از Drag-and-Drop برای انتقال کارت‌ها بین ستون‌ها (To Do → In Progress → Done) استفاده می‌کنند. در طول کشیدن، کارت از ستون مبدا جدا شده، انگشت را دنبال می‌کند و پس از عبور از مرز ستون دیگر با انیمیشن درج می‌شود. iOS 11+ از UIDragPreview با افکت پارالاکس پشتیبانی می‌کند که در آن preview کمی از نقطه لمس منحرف شده و عمق ایجاد می‌کند.

بخش‌های Springboard (iOS) — کشیدن آیکون‌های برنامه در صفحه اصلی iOS. فشار دراز روی آیکون حالت «jiggling» (لرزش آیکون‌ها) را فعال می‌کند، سپس کاربر می‌تواند آیکون‌ها را بین صفحات جابجا کرده و پوشه‌ها ایجاد کند. این یکی از پیچیده‌ترین الگوهای UX DnD است چون نیازمند پردازش همزمان کشیدن، انیمیشن لرزش و گروه‌بندی در پوشه‌ها است.

توصیه‌های UX برای Drag-and-Drop

بازخورد بصری — برای Drag-and-Drop بسیار حیاتی است. شیء کشیده شده باید تغییر کند: کوچکتر شود (iOS: scale 0.8–0.9)، نیمه شفاف شود (alpha 0.7–0.8) و با سایه از رابط بالاتر برود (shadow offset). Drop target باید به نزدیک شدن واکنش بصری نشان دهد: روشن شود (highlight)، گسترش یابد (expand) یا مرزها را نشان دهد (border). بدون این سیگنال‌ها، کاربر نمی‌داند شیء را کجا می‌تواند رها کند.

انیمیشن بازگشت (drag cancel) — اگر کاربر عنصر را خارج از منطقه رهایش یا در بالای منطقه نامعتبر رها کند، شیء باید با انیمیشن به مکان اصلی بازگردد. iOS UIDragInteractionDelegate روش‌های dragInteraction(_:sessionDidMove:) برای پیگیری و dragInteraction(_:session:willEndWith:) برای انیمیشن بازگشت را فراهم می‌کند. Android View.setOnDragListener ACTION_DRAG_ENDED را دریافت می‌کند که در آن می‌توان انیمیشن بازگشت را از طریق ValueAnimator یا ObjectAnimator آغاز کرد.

توصیهiOSAndroid
گیرفتاری با حرکتLong Press (پیش‌فرض)OnLongClickListener
Drag previewUIDragItem.previewProviderDragShadowBuilder
بازخورد لامسیUIImpactFeedbackGeneratorHapticFeedbackConstants.LONG_PRESS
انیمیشن بازگشتUIDragPreviewTargetViewPropertyAnimator
Drop proposalUIDropProposal (.move/.copy)ACTION_DROP + فلگ‌ها
DnD بین برنامه‌ایiOS 11+ Split View (iPad)Android 7.0+ Split Screen

دسترس‌پذیری: کاربران با محدودیت‌های حرکتی ممکن است نتوانند حرکت کشیدن را انجام دهند. از طریق دکمه‌های «حرکت به بالا/پایین» برای لیست‌ها، منوی کتکستی «انتقال به پوشه» برای فایل‌ها جایگزین‌هایی فراهم کنید. iOS VoiceOver از عمل روتر «Drag» برای جابجایی عناصر پشتیبانی می‌کند. Android TalkBack از طریق AccessibilityNodeInfo.addAction() اعمال سفارشی را فراهم می‌کند. Nike Run Club و Apple Health از DnD برای تغییر ترتیب متریک‌ها در داشبورد استفاده می‌کنند — با دسترسی از طریق دکمه‌های استاندارد.

سوالات متداول

کدام حرکت برای شروع Drag-and-Drop استفاده می‌شود؟

حرکت استاندارد برای شروع Drag-and-Drop Long Press (فشار دراز) به مدت 300–500 میلی‌ثانیه است. iOS از مکانیسم ساخته UIDragInteraction استفاده می‌کند که به طور آتوماتیک لمس طولانی را به گیرفتاری تبدیل می‌کند. Android نیازمند فراخوان صریح startDragAndDrop() در فراخوان OnLongClickListener است. در بعضی موارد (مثلاً در بازی‌ها)، DnD ممکن است با یک لمس ساده بدون تأخیر شروع شود.

آیا می‌توان اشیاء را بین برنامه‌های مختلف کشید؟

بله، Drag-and-Drop بین برنامه‌ای در iOS 11+ (iPad) و Android 7.0+ پشتیبانی می‌شود. در iPad، کشیدن در حالت Split View و Slide Over کار می‌کند — کاربر می‌تواند متنی از Safari گرفته و به یادداشت‌ها منتقل کند. در Android، DnD بین برنامه‌ها در Split Screen کار می‌کند. داده‌ها از طریق UIPasteConfiguration (iOS) یا ClipData (Android) با مشخص کردن نوع‌های پشتیبانی شده (UTI، MIME) انتقال می‌یابند.

چگونه می‌توان از تعارض Drag-and-Drop با پیمایش جلوگیری کرد؟

تعارض DnD و Scroll از طریق تأخیر در گیرفتاری حل می‌شود. اگر کاربر حرکت انگشت را کمتر از مهل زمانی Long Press (500 میلی‌ثانیه) آغاز کند، حرکت به عنوان پیمایش تفسیر می‌شود نه Drag-and-Drop. در iOS، UIDragInteraction این تعارض را به طور آتوماتیک از طریق cancelsTouchesInView مدیریت می‌کند. در Android، ItemTouchHelper از آستانه استفاده می‌کند — اگر حرکت از آستانه TouchSlop تجاوز کند، Long Press به نفع پیمایش لغو می‌شود.

چه داده‌هایی را می‌توان در طول کشیدن انتقال داد؟

Drag-and-Drop از هر نوع داده‌ای پشتیبانی می‌کند: متن، تصاویر، فایل‌ها، URL، اشیاء سفارشی. iOS از NSItemProvider با نوع‌های UTI استفاده می‌کند (public.text، public.image، public.file-url). Android — ClipData با نوع‌های MIME (text/plain، image/png، application/octet-stream). برای داده‌های سفارشی، ClipData.Item با Intent ایجاد می‌شود. در DnD بین برنامه‌ای، داده‌ها در قالب‌های جهانی بسته می‌شوند: plain text، HTML، RTF، UIImage/PNG.

چگونه بازگشت عنصر را در صورت لغو Drag-and-Drop انیمیت کنیم؟

در iOS، انیمیشن بازگشت از طریق UIDragPreviewTarget انجام می‌شود — مکان نهایی که preview با انیمیشن به آن باز می‌گردد. در Android از ViewPropertyAnimator با translateX/translateY برای بازگرداندن عنصر به مکان اصلی استفاده کنید. زمان انیمیشن — 200–300 میلی‌ثانیه با منحنی easing (EaseOut). UIKit به طور آتوماتیک UIDragPreview را با افکت پارالاکس اضافه می‌کند که در صورت لغو حرکت به طور صاف باز می‌گردد.

نتیجه

  • Drag-and-Drop — روش کشیدن اشیاء با سه مرحله: گیرفتاری، جابجایی، رها کردن
  • شروع — معمولاً از طریق Long Press (300–500 میلی‌ثانیه) برای تمایز از پیمایش
  • iOS API — UIDragInteraction (مبدا) + UIDropInteraction (گیرنده)
  • Android API — View.startDragAndDrop() (مبدا) + View.setOnDragListener (گیرنده)
  • ItemTouchHelper — راه‌حل آماده Android برای تغییر ترتیب در RecyclerView
  • Drag preview — سایه بصری شیء که با نیمه شفافیت انگشت را دنبال می‌کند
  • انیمیشن بازگشت — در صورت رهایش در خارج از منطقه معتبر برای UX قابل فهم اجباری است

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید