Swipe: τι είναι, επεξεργασία σαρώσεων στην ανάπτυξη κινητών

Συγγραφέας: IT Sectr Δημοσιεύτηκε: 2026-02-27 Χρόνος ανάγνωσης: 8 λεπ
Swipe (σάρωση) — μια διακριτή χειρονομία κατά την οποία ο χρήστης μετακινεί το δάχτυλο στην οθόνη προς μία κατεύθυνση — δεξιά, αριστερά, πάνω ή κάτω. Σε αντίθεση με το σύρσιμο (drag), η σάρωση δεν παρακολουθεί συνεχή κίνηση: αναγνωρίζεται ως ολοκληρωμένη ενέργεια αφού το δάχτυλο ξεπεράσει το ελάχιστο όριο και απομακρυνθεί από την οθόνη. Σύμφωνα με την έρευνα UX της Nielsen Norman Group (2024), η σάρωση είναι η δεύτερη συχνότερη χειρονομία σε εφαρμογές κινητών μετά το πάτημα, που χρησιμοποιείται στο 23% των αλληλεπιδράσεων χρηστών.

Βασικά σημεία

  • Swipe — διακριτή χειρονομία: αναγνωρίζεται ως μία ολοκληρωμένη ενέργεια μετά την υπέρβαση του ορίου και την απομάκρυνση του δαχτύλου.
  • Στο iOS, η επεξεργασία σάρωσης γίνεται μέσω UISwipeGestureRecognizer με ρύθμιση κατεύθυνσης (direction) και αριθμού δαχτύλων.
  • Στο Android χρησιμοποιείται GestureDetector με onFling(MotionEvent) ή OnSwipeTouchListener για απλοποιημένο API.
  • Το όριο σάρωσης — ~20px στο iOS (viewConfiguration) και ρυθμίζεται μέσω VelocityTracker στο Android.
  • Για λίστες (UITableView/RecyclerView) χρησιμοποιούνται ενσωματωμένοι μηχανισμοί — UISwipeActionsConfiguration και ItemTouchHelper — αντί για χειροκίνητη αναγνώριση.

Τι είναι το swipe;

Swipe — μια γρήγορη ολισθαίνουσα κίνηση του δαχτύλου στην επιφάνεια της οθόνης που τελειώνει με απομάκρυνση. Η σάρωση μπορεί να είναι σύντομη (κύλιση στοιχείου) ή μεγάλη (άνοιγμα κουρτίνας), αλλά το βασικό χαρακτηριστικό είναι η διακριτότητα: το σύστημα την αναγνωρίζει ως ένα γεγονός, όχι ως συνεχή ακολουθία συντεταγμένων.

Τα κινητά ΛΣ καθορίζουν τη σάρωση με τρεις παραμέτρους: ελάχιστη απόσταση (όριο), ελάχιστη ταχύτητα (velocity) και κατεύθυνση. Αν το δάχτυλο κινείται αργά ή η απόσταση δεν είναι επαρκής, το σύστημα ερμηνεύει τη χειρονομία ως μετατόπιση (pan) ή πάτημα. Οι τιμές ορίων διαφέρουν μεταξύ πλατφορμών: το iOS χρησιμοποιεί τη σταθερά UISwipeGestureRecognizer με σταθερό όριο, το Android — ViewConfiguration.getScaledTouchSlop(), που επιστρέφει ~8–16 dp ανάλογα με την πυκνότητα οθόνης.

Σύμφωνα με το Android Developers Documentation, το onFling (swipe) στο GestureDetector ενεργοποιείται σε ταχύτητα άνω των 100 px/s και απόσταση από 50px. Στην IT Sectr χρησιμοποιούμε τη σάρωση για πλοήγηση (γκάλερι, διεπαφές καρτών, onboarding) — αυτή η χειρονομία είναι διαισθητική για χρήστες όλων των ηλικιών.

Swipe vs μετατόπιση: ποια η διαφορά;

Swipe και μετατόπιση (pan/drag) είναι διαφορετικοί τύποι χειρονομιών, αν και και οι δύο χρησιμοποιούν κίνηση του δαχτύλου στην οθόνη. Η σάρωση είναι διακριτή και σημαίνει „κάνε μία ενέργεια”, ενώ η μετατόπιση είναι συνεχής και σημαίνει „μετακίνησε το αντικείμενο όσο το δάχτυλο είναι στην οθόνη”.

Παράμετρος Swipe Μετατόπιση (Pan/Drag)
Τύπος Διακριτός Συνεχής
Γεγονότα Ένα (αναγνωρίστηκε/δεν αναγνωρίστηκε) Πολλαπλά (.began → .changed → .ended)
Ταχύτητα Υψηλή (γρήγορη κίνηση) Οποιαδήποτε (αργή κίνηση)
Παράδειγμα iOS UISwipeGestureRecognizer UIPanGestureRecognizer
Παράδειγμα Android GestureDetector.onFling() GestureDetector.onScroll()
Σενάριο Διαγραφή email, γύρισμα σελίδας Μετακίνηση χάρτη, σύρσιμο αρχείου
Παρακολούθηση συντεταγμένων Όχι (μόνο κατεύθυνση) Ναι (συνεχής ενημέρωση συντεταγμένων)

Η επιλογή μεταξύ σάρωσης και μετατόπισης εξαρτάται από την εργασία. Για ενέργειες στο στοιχείο (διαγραφή, αρχειοθέτηση, άνοιγμα μενού) χρησιμοποιήστε σάρωση. Για άμεσο χειρισμό (μετακίνηση, κλίμακα) — μετατόπιση. Η ανάμειξη χειρονομιών στο ίδιο στοιχείο απαιτεί require(toFail:) ή προσαρμοσμένη λογική.

Swipe στο iOS: UISwipeGestureRecognizer

UISwipeGestureRecognizer — μια υποκλάση του UIGestureRecognizer που αναγνωρίζει διακριτή σάρωση σε μία από τέσσερις κατευθύνσεις. Σε αντίθεση με το UIPanGestureRecognizer, δεν δημιουργεί ενδιάμεσα γεγονότα .changed: κατά την αναγνώριση, το action καλείται ακριβώς μία φορά.

Η ιδιότητα direction (UISwipeGestureRecognizer.Direction) ορίζει την παρακολουθούμενη κατεύθυνση — .left, .right, .up, .down. Μπορεί να συνδυαστεί μέσω μάσκας: [.left, .right] για οριζόντιες σαρώσεις. Η ιδιότητα numberOfTouchesRequired καθορίζει τον αριθμό δαχτύλων — προεπιλογή 1. Το UISwipeGestureRecognizer δεν έχει ρυθμιζόμενο όριο απόστασης — το iOS χρησιμοποιεί ενσωματωμένη τιμή περίπου 20px, επαρκή για αξιόπιστη αναγνώριση.

Δεδομένου ότι το UISwipeGestureRecogniser είναι διακριτός αναγνωριστής, δεν συγκρούεται με το UIPanGestureRecognizer: σε αργή κίνηση ενεργοποιείται το pan, σε γρήγορη — το swipe. Ωστόσο, όταν συνυπάρχει με UITapGestureRecognizer στο ίδιο view, μπορεί να απαιτηθεί require(toFail:) για την αποφυγή εσφαλμένης αναγνώρισης πατήματος.

Swipe στο Android: GestureDetector

Στο Android, το κύριο API για αναγνώριση σάρωσης είναι το GestureDetector με callback OnGestureListener, συγκεκριμένα η μέθοδος onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY). Το GestureDetector αναλύει την αρχική και τελική θέση του δαχτύλου, την ταχύτητα κίνησης κατά άξονες και την απόσταση, και στη συνέχεια καλεί το onFling όταν υπερβαίνει τα όρια.

Τα ελάχιστα όρια ρυθμίζονται μέσω ViewConfiguration: VelocityTracker.getMinVelocity() (~100 px/s) και ViewConfiguration.getScaledTouchSlop() (~8–16 dp). Το προσαρμοσμένο OnSwipeTouchListener είναι ένα διαδεδομένο μοτίβο που απλοποιεί το API: ο προγραμματιστής δεν χρειάζεται να υπολογίζει χειροκίνητα την κατεύθυνση και την ταχύτητα. Η Android Support Library δεν περιέχει ενσωματωμένο „SwipeDetector”, επομένως το προσαρμοσμένο περιτύλιγμα είναι η τυπική λύση.

Για σάρωση σε λίστες, η Google συνιστά τη χρήση ItemTouchHelper.SimpleCallback από το RecyclerView, το οποίο αφαιρεί την ανίχνευση χειρονομίας, την κίνηση και τα callbacks onSwiped(). Στην IT Sectr χρησιμοποιούμε προσαρμοσμένο SwipeListener για ViewPager2 και διεπαφές καρτών — αυτό παρέχει έλεγχο της ευαισθησίας σάρωσης χωρίς επιβάρυνση της απόδοσης.

Swipe σε λίστες: SwipeActions και ItemTouchHelper

Για λίστες (UITableView, RecyclerView) η Apple και η Google παρέχουν εξειδικευμένα API που αντικαθιστούν τη μη αυτόματη προσθήκη UISwipeGestureRecognizer. Αυτά τα API υποστηρίζουν κουμπιά ενεργειών, προσαρμοσμένη κίνηση και χειρονομίες „σύρετε για διαγραφή” — τυπικά μοτίβα εφαρμογών κινητών.

Στο iOS (11+) χρησιμοποιείται UISwipeActionsConfiguration: η μέθοδος tableView(_:leadingSwipeActionsConfigurationForRowAt:) επιστρέφει έναν πίνακα UIContextualAction — κουμπιά με τίτλο, στυλ (destructive, normal) και χειριστή. Για παράδειγμα, „Διαγραφή” — .destructive με κόκκινο φόντο, „Αρχειοθέτηση” — .normal με γκρι. Το σύστημα κινεί αυτόματα την εμφάνιση των κουμπιών και καλεί το completion block μετά το πάτημα.

Στο Android, το ItemTouchHelper.SimpleCallback συνδέεται στο RecyclerView μέσω ItemTouchHelper.attachToRecyclerView(). Παράμετροι — σημαίες κατεύθυνσης (start, end, up, down) και callback onSwiped(viewHolder, direction). Μέσα στο onSwiped καλείται adapter.notifyItemRemoved(position) για διαγραφή στοιχείου με κίνηση. Το ItemTouchHelper χειρίζεται αυτόματα χειρονομίες, συγκρούσεις με κύλιση (scroll) και επιστροφή στοιχείου αν η σάρωση δεν ολοκληρωθεί. Σύμφωνα με το Google I/O 2024, το ItemTouchHelper χρησιμοποιείται στο 70% των εφαρμογών Android με ενέργειες σάρωσης σε λίστες.

Παραδείγματα κώδικα σε Swift και Kotlin

Παράδειγμα 1: Σάρωση αριστερά στο iOS (Swift)

Προσθέτει UISwipeGestureRecognizer στο view για επιστροφή στην προηγούμενη οθόνη. Ο κώδικας δείχνει την ελάχιστη διαμόρφωση του αναγνωριστή με κατεύθυνση .left.

swift
import UIKit

class CardViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let swipeLeft = UISwipeGestureRecognizer(
            target: self,
            action: #selector(handleSwipeLeft(_:))
        )
        swipeLeft.direction = .left
        swipeLeft.numberOfTouchesRequired = 1
        view.addGestureRecognizer(swipeLeft)
    }

    @objc private func handleSwipeLeft(_: UISwipeGestureRecognizer) {
        guard let nav = navigationController else { return }
        if nav.viewControllers.count > 1 {
            nav.popViewController(animated: true)
        } else {
            nav.dismiss(animated: true)
        }
    }
}

Ο αναγνωριστής συνδέεται στο root-view του ελεγκτή. Ο έλεγχος navigationController.viewControllers.count εγγυάται ότι το pop εκτελείται μόνο όταν υπάρχει προηγούμενη οθόνη στη στοίβα. Για modal ελεγκτές χρησιμοποιείται dismiss. Ο κώδικας δεν απαιτεί έλεγχο κατάστασης — το UISwipeGestureRecognizer είναι διακριτό και καλεί το action μόνο σε επιτυχή αναγνώριση.

Παράδειγμα 2: Σάρωση στο Android (Kotlin) με προσαρμοσμένο OnSwipeTouchListener

Υλοποιεί ένα απλό περιτύλιγμα GestureDetector που καθορίζει την κατεύθυνση σάρωσης και καλεί τα callbacks onSwipeLeft/Right.

kotlin
import android.content.Context
import android.view.GestureDetector
import android.view.MotionEvent
import android.view.View

open class OnSwipeTouchListener(context: Context) : View.OnTouchListener {

    private val gestureDetector = GestureDetector(context, GestureListener())

    override fun onTouch(v: View, event: MotionEvent): Boolean {
        return gestureDetector.onTouchEvent(event)
    }

    private inner class GestureListener : GestureDetector.SimpleOnGestureListener() {

        companion object {
            private const val SWIPE_THRESHOLD = 100
            private const val SWIPE_VELOCITY_THRESHOLD = 100
        }

        override fun onFling(
            e1: MotionEvent?,
            e2: MotionEvent,
            velocityX: Float,
            velocityY: Float
        ): Boolean {
            val diffX = e2.x - e1!!.x
            val diffY = e2.y - e1.y

            if (Math.abs(diffX) > Math.abs(diffY)) {
                if (Math.abs(diffX) > SWIPE_THRESHOLD
                    && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD
                ) {
                    if (diffX > 0) onSwipeRight()
                    else onSwipeLeft()
                    return true
                }
            } else {
                if (Math.abs(diffY) > SWIPE_THRESHOLD
                    && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD
                ) {
                    if (diffY > 0) onSwipeDown()
                    else onSwipeUp()
                    return true
                }
            }
            return false
        }
    }

    open fun onSwipeLeft() {}
    open fun onSwipeRight() {}
    open fun onSwipeUp() {}
    open fun onSwipeDown() {}
}

Το OnSwipeTouchListener επεκτείνει το SimpleOnGestureListener, υλοποιώντας το onFling. Τα diffX/diffY καθορίζουν την κατεύθυνση, SWIPE_THRESHOLD (100px) και SWIPE_VELOCITY_THRESHOLD (100 px/s) — όρια. Χρήση: view.setOnTouchListener(OnSwipeTouchListener(context).apply { onSwipeLeft = { dismiss() } }).

Παράδειγμα 3: SwipeActions στο iOS (UITableView)

Προσθέτει κουμπί διαγραφής κατά τη σάρωση αριστερά στο κελί πίνακα. Χρησιμοποιεί ενσωματωμένο API iOS 11+ χωρίς μη αυτόματη αναγνώριση χειρονομιών.

swift
func tableView(
    _ tableView: UITableView,
    trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath
) -> UISwipeActionsConfiguration? {
    let deleteAction = UIContextualAction(
        style: .destructive,
        title: "Διαγραφή"
    ) { _, _, completionHandler in
        items.remove(at: indexPath.row)
        tableView.deleteRows(at: [indexPath], with: .automatic)
        completionHandler(true)
    }
    deleteAction.backgroundColor = .systemRed

    let config = UISwipeActionsConfiguration(actions: [deleteAction])
    config.performsFirstActionWithFullSwipe = true
    return config
}

Η μέθοδος επιστρέφει UISwipeActionsConfiguration με πίνακα UIContextualAction. style: .destructive ορίζει αυτόματα κόκκινο φόντο. performsFirstActionWithFullSwipe = true επιτρέπει την εκτέλεση ενέργειας με πλήρη σάρωση χωρίς πρόσθετο πάτημα. Στην IT Sectr χρησιμοποιούμε αυτό το API για όλες τις λίστες με ενέργειες — είναι τυποποιημένο, υποστηρίζει VoiceOver και δεν απαιτεί προσαρμοσμένα GestureRecognizer.

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

Πώς να ξεχωρίσουμε τη σάρωση από τη μετατόπιση;

Swipe — διακριτή χειρονομία με γρήγορη κίνηση και απομάκρυνση δαχτύλου, μετατόπιση — συνεχές σύρσιμο με παρακολούθηση συντεταγμένων. Το UISwipeGestureRecognizer ενεργοποιείται μία φορά, το UIPanGestureRecognizer δημιουργεί .began → .changed → .ended. Η επιλογή εξαρτάται από το σενάριο: swipe — για ενέργειες (διαγραφή, γύρισμα), pan — για μετακίνηση (χάρτης, ρυθμιστικό).

Λειτουργεί η σάρωση το ίδιο σε iOS και Android;

Η λογική της χειρονομίας είναι ταυτόσημη, αλλά το API διαφέρει. Το iOS χρησιμοποιεί UISwipeGestureRecognizer με direction. Το Android χρησιμοποιεί GestureDetector.onFling() με προσαρμοσμένα όρια. Το αποτέλεσμα — ίδιο UX με διαφορετική υλοποίηση. Τα cross-platform frameworks (Flutter, React Native) αφαιρούν τη διαφορά μέσω ενιαίου API σάρωσης.

Πώς να χειριστούμε τη σάρωση σε λίστα;

Στο iOS (11+) χρησιμοποιήστε UISwipeActionsConfiguration στο UITableViewDelegate. Στο Android — ItemTouchHelper.SimpleCallback για RecyclerView. Αυτά τα API αντικαθιστούν τα μη αυτόματα GestureRecognizer, υποστηρίζουν κουμπιά ενεργειών και κίνηση, χειρίζονται σωστά τη σύγκρουση με κύλιση και προσαρμόζονται στα HIG πλατφόρμας.

Σύνοψη

  • Swipe — διακριτή χειρονομία γρήγορης ολίσθησης δαχτύλου, δεύτερη σε συχνότητα μετά το πάτημα (23% αλληλεπιδράσεων).
  • Στο iOS το UISwipeGestureRecogniser επεξεργάζεται σαρώσεις σε τέσσερις κατευθύνσεις με σταθερό όριο ~20px.
  • Στο Android το GestureDetector.onFling() χρησιμοποιείται με προσαρμοσμένα όρια ταχύτητας και απόστασης.
  • Για λίστες χρησιμοποιήστε UISwipeActionsConfiguration (iOS) και ItemTouchHelper (Android) αντί για μη αυτόματους αναγνωριστές.
  • Η σάρωση διαφέρει από τη μετατόπιση στη διακριτότητα και την υψηλή ταχύτητα — μην μπερδεύετε αυτές τις χειρονομίες στο σχεδιασμό.
  • Το προσαρμοσμένο OnSwipeTouchListener στο Android απλοποιεί το API GestureDetector κρύβοντας τον υπολογισμό κατεύθυνσης.
  • Στην IT Sectr εφαρμόζουμε σάρωση για πλοήγηση, διαγραφή στοιχείων και onboarding — η χειρονομία είναι διαισθητική και δεν απαιτεί εκμάθηση.

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

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

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

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