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 — η μέθοδος View του Android για την έναρξη της μεταφοράς μετά τη σύλληψη
  • 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 session, συλλαμβάνει τα δεδομένα του αντικειμένου και εμφανίζει το drag preview — ένα ημιδιαφανές αντίγραφο του στοιχείου που ακολουθεί το δάχτυλο. Σε αυτή τη φάση το σύστημα απορρίπτει άλλες χειρονομίες (κύλιση, επιλογή κειμένου) μέχρι την ολοκλήρωση του DnD.

Φάση 2 — μετακίνηση (Drag Move): το δάχτυλο κινείται στην οθόνη και το drag preview ακολουθεί το σημείο επαφής. Το σύστημα προσδιορίζει συνεχώς το drop target κάτω από το δάχτυλο και στέλνει τα γεγονότα drag enter, drag move και drag exit. Το drop target μπορεί να αντιδρά οπτικά: να φωτίζεται, να επεκτείνεται ή να εμφανίζει μια γραμμή εισαγωγής. Αυτή η φάση διαρκεί από 0,5 έως 10+ δευτερόλεπτα ανάλογα με την πολυπλοκότητα της εργασίας.

Φάση 3 — απόλυση (Drop): το δάχτυλο απομακρύνεται από την οθόνη. Το σύστημα ολοκληρώνει τη drag session και καλεί το drop callback του στοιχείου-στόχου. Αν το drop target απορρίψει την απόλυση (π.χ. μεταφορά αρχείου σε φάκελο χωρίς δικαιώματα εγγραφής), το drag preview επιστρέφει με κίνηση στην αρχική θέση (cancel animation). Αν η απόλυση γίνει αποδεκτή, το στοιχείο εξαφανίζεται από την αρχική θέση και εμφανίζεται στη θέση προορισμού.

ΦάσηΓεγονός iOSΓεγονός AndroidΟπτική κατάσταση
ΣύλληψηUIDragInteractionDelegate.dragSessionWillBeginView.OnLongClickListener → startDragAndDropΤο drag 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. Ο delegate καθορίζει ποια στοιχεία μεταφέρονται, την εμφάνιση και τη συμπεριφορά τους. Για τη λήψη στοιχείων χρησιμοποιείται το 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("στοιχείο", 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(). Ο listener λαμβάνει τα γεγονότα 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: ο χρήστης μεταφέρει στοιχεία της λίστας για να αλλάξει τη σειρά τους. Παραδείγματα: αναδιάταξη επαφών στα αγαπημένα, ταξινόμηση εργασιών σε trackers (Trello, Todoist), αλλαγή σειράς τραγουδιών σε λίστα αναπαραγωγής (Spotify, Apple Music). Υλοποιείται μέσω του ItemTouchHelper στο Android ή του UILongPressGestureRecognizer + αναδιάταξη κελιών στο iOS.

Διαχειριστές αρχείων — Drag-and-Drop για αντιγραφή και μεταφορά αρχείων μεταξύ φακέλων. Το Files App του iOS, το Files by Google του Android, το Dropbox — όλα υποστηρίζουν DnD. Η μεταφορά ενός αρχείου πάνω σε έναν φάκελο τον μετακινεί μέσα σε αυτόν (move), ενώ η μεταφορά με πατημένο το πλήκτρο Option/Ctrl το αντιγράφει (copy). Το drop target φωτίζεται οπτικά κατά την προσέγγιση, δείχνοντας τα όρια του φακέλου.

Πίνακες Kanban — το Trello, το Jira, το Notion χρησιμοποιούν Drag-and-Drop για τη μεταφορά καρτών μεταξύ στηλών (To Do → In Progress → Done). Κατά τη μεταφορά η κάρτα αποσπάται από την αρχική στήλη, ακολουθεί το δάχτυλο και, όταν διασχίσει τα όρια μιας άλλης στήλης, εισάγεται με κίνηση. Το iOS 11+ υποστηρίζει το UIDragPreview με εφέ παράλλαξης, όπου το preview αποκλίνει ελαφρώς από το σημείο επαφής, δημιουργώντας βάθος.

Ενότητες Springboard (iOS) — μεταφορά εικονιδίων εφαρμογών στην αρχική οθόνη του iOS. Το παρατεταμένο πάτημα σε ένα εικονίδιο ενεργοποιεί τη λειτουργία "jiggling" (τα εικονίδια ταλαντεύονται), μετά από το οποίο ο χρήστης μπορεί να μετακινεί εικονίδια μεταξύ σελίδων και να δημιουργεί φακέλους. Αυτό είναι ένα από τα πιο πολύπλοκα UX patterns του 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 (default)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

Προσβασιμότητα: οι χρήστες με κινητικούς περιορισμούς ενδέχεται να μην μπορούν να εκτελέσουν τη χειρονομία μεταφοράς. Παρέχετε εναλλακτικές μέσω κουμπιών "Move Up/Down" για τις λίστες και μενού περιβάλλοντος "Move to Folder" για τα αρχεία. Το VoiceOver του iOS υποστηρίζει τη δράση ρότορα "Drag" για τη μετακίνηση στοιχείων. Το TalkBack του Android παρέχει προσαρμοσμένες δράσεις μέσω του AccessibilityNodeInfo.addAction(). Το Nike Run Club και το Apple Health χρησιμοποιούν DnD για την αναδιάταξη μετρήσεων στον πίνακα ελέγχου — με πρόσβαση μέσω τυπικών κουμπιών.

Συχνές ερωτήσεις

Ποια χειρονομία χρησιμοποιείται για την εκκίνηση του Drag-and-Drop;

Η τυπική χειρονομία για την έναρξη του Drag-and-Drop — το Long Press (παρατεταμένο πάτημα) διάρκειας 300–500 χιλιοστών του δευτερολέπτου. Το iOS χρησιμοποιεί τον ενσωματωμένο μηχανισμό UIDragInteraction, ο οποίος μετατρέπει αυτόματα το παρατεταμένο άγγιγμα σε σύλληψη. Το Android απαιτεί ρητή κλήση του startDragAndDrop() στο callback του 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 επιλύεται μέσω της καθυστέρησης της σύλληψης. Αν ο χρήστης αρχίσει να κινεί το δάχτυλο πριν λήξει το timeout του Long Press (500 χιλιοστά του δευτερολέπτου), η χειρονομία ερμηνεύεται ως κύλιση και όχι ως Drag-and-Drop. Στο iOS το UIDragInteraction διαχειρίζεται αυτόματα αυτή τη σύγκρουση μέσω του cancelsTouchesInView. Στο Android το ItemTouchHelper χρησιμοποιεί threshold — αν η κίνηση υπερβεί το όριο 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 ms) για τη διάκριση από την κύλιση
  • iOS API — UIDragInteraction (πηγή) + UIDropInteraction (δέκτης)
  • Android API — View.startDragAndDrop() (πηγή) + View.setOnDragListener (δέκτης)
  • ItemTouchHelper — έτοιμη λύση του Android για αναδιάταξη στο RecyclerView
  • Drag preview — οπτική σκιά του αντικειμένου που ακολουθεί το δάχτυλο με ημιδιαφάνεια
  • Κίνηση επιστροφής — απαραίτητη κατά την απόλυση εκτός έγκυρης ζώνης για κατανοητό UX

Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση

Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.

Συζήτηση έργου

Διαβάστε επίσης