Swipe: cos'è, gestione degli swipe nello sviluppo mobile

Autore: IT Sectr Pubblicato: 2026-02-27 Tempo di lettura: 8 min
Swipe (scorrimento) è un gesto discreto in cui l'utente muove un dito sullo schermo in una direzione — destra, sinistra, su o giù. A differenza del trascinamento (drag), lo swipe non traccia il movimento continuo: viene riconosciuto come un'azione completata dopo che il dito ha superato una soglia minima e si è sollevato dallo schermo. Secondo uno studio UX di Nielsen Norman Group (2024), lo swipe è il secondo gesto più frequente nelle app mobili dopo il tocco, utilizzato nel 23% delle interazioni utente.

Punti chiave

  • Lo swipe è un gesto discreto: riconosciuto come un'azione completata dopo il superamento della soglia e il sollevamento del dito.
  • In iOS, la gestione dello swipe avviene tramite UISwipeGestureRecognizer con configurazione di direzione e numero di dita.
  • In Android, si usa GestureDetector con onFling(MotionEvent) o OnSwipeTouchListener per un'API semplificata.
  • La soglia di swipe è di ~20px su iOS (viewConfiguration) e configurabile tramite VelocityTracker in Android.
  • Per le liste (UITableView/RecyclerView), si usano meccanismi integrati — UISwipeActionsConfiguration e ItemTouchHelper — invece del riconoscimento manuale.

Cos'è uno swipe?

Lo swipe è un movimento rapido e scorrevole del dito sulla superficie dello schermo, che termina con il sollevamento. Uno swipe può essere corto (sfogliare un elemento) o lungo (aprire una tendina), ma la caratteristica principale è la discretezza: il sistema lo riconosce come un singolo evento, non come una sequenza continua di coordinate.

I sistemi operativi mobili rilevano uno swipe in base a tre parametri: distanza minima (soglia), velocità minima (velocity) e direzione. Se il dito si muove lentamente o la distanza è insufficiente, il sistema interpreta il gesto come panoramica o tocco. I valori di soglia differiscono tra le piattaforme: iOS usa una costante in UISwipeGestureRecognizer con una soglia fissa, Android usa ViewConfiguration.getScaledTouchSlop(), che restituisce ~8–16 dp a seconda della densità dello schermo.

Secondo la Documentazione per sviluppatori Android, onFling (swipe) in GestureDetector si attiva a velocità superiori a 100 px/s e distanze da 50px. Presso IT Sectr, usiamo lo swipe per la navigazione (gallerie, interfacce a carte, onboarding) — questo gesto è intuitivo per utenti di tutte le età.

Swipe vs panoramica: qual è la differenza?

Lo swipe e la panoramica (pan/drag) sono diversi tipi di gesti, sebbene entrambi comportino lo spostamento di un dito sullo schermo. Lo swipe è discreto e significa "eseguire un'azione", mentre la panoramica è continua e significa "spostare un oggetto finché il dito è sullo schermo".

Parametro Swipe Pan/Drag
Tipo Discreto Continuo
Eventi Singolo (riconosciuto/non riconosciuto) Multipli (.began → .changed → .ended)
Velocità Alta (movimento rapido) Qualsiasi (movimento lento)
Esempio iOS UISwipeGestureRecognizer UIPanGestureRecognizer
Esempio Android GestureDetector.onFling() GestureDetector.onScroll()
Scenario Eliminare un'email, girare pagina Spostare una mappa, trascinare un file
Tracciamento coordinate No (solo direzione) Sì (aggiornamento costante delle coordinate)

La scelta tra swipe e panoramica dipende dal compito. Per azioni su un elemento (eliminare, archiviare, aprire menu) usa lo swipe. Per la manipolazione diretta (spostare, ridimensionare) usa la panoramica. Mescolare gesti sullo stesso elemento richiede require(toFail:) o logica personalizzata.

Swipe in iOS: UISwipeGestureRecognizer

UISwipeGestureRecognizer è una sottoclasse di UIGestureRecognizer che riconosce uno swipe discreto in una delle quattro direzioni. A differenza di UIPanGestureRecognizer, non genera eventi .changed intermedi: quando riconosciuto, l'azione viene chiamata esattamente una volta.

La proprietà direction (UISwipeGestureRecognizer.Direction) imposta la direzione tracciata — .left, .right, .up, .down. Le direzioni possono essere combinate tramite una maschera: [.left, .right] per gli swipe orizzontali. La proprietà numberOfTouchesRequired determina il numero di dita — 1 per impostazione predefinita. UISwipeGestureRecognizer non ha una soglia di distanza configurabile — iOS utilizza un valore incorporato di circa 20px, sufficiente per un riconoscimento affidabile.

Poiché UISwipeGestureRecognizer è un riconoscitore discreto, non entra in conflitto con UIPanGestureRecognizer: il movimento lento attiva pan, quello rapido attiva swipe. Tuttavia, in coesistenza con UITapGestureRecognizer sulla stessa vista, potrebbe essere necessario require(toFail:) per prevenire un falso riconoscimento del tocco.

Swipe in Android: GestureDetector

In Android, l'API principale per il riconoscimento dello swipe è GestureDetector con il callback OnGestureListener, in particolare il metodo onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY). GestureDetector analizza la posizione iniziale e finale del dito, la velocità di movimento lungo gli assi e la distanza, quindi chiama onFling quando le soglie vengono superate.

Le soglie minime sono configurabili tramite ViewConfiguration: VelocityTracker.getMinVelocity() (~100 px/s) e ViewConfiguration.getScaledTouchSlop() (~8–16 dp). Un OnSwipeTouchListener personalizzato è un pattern comune che semplifica l'API: lo sviluppatore non deve calcolare manualmente direzione e velocità. La Android Support Library non contiene un "SwipeDetector" incorporato, quindi un wrapper personalizzato è la soluzione standard.

Per lo swipe nelle liste, Google raccomanda di usare ItemTouchHelper.SimpleCallback di RecyclerView, che astrae il rilevamento del gesto, l'animazione e i callback onSwiped(). Presso IT Sectr, usiamo un SwipeListener personalizzato per ViewPager2 e interfacce a carte — questo dà controllo sulla sensibilità dello swipe senza sacrificare le prestazioni.

Swipe nelle liste: SwipeActions e ItemTouchHelper

Per le liste (UITableView, RecyclerView), Apple e Google forniscono API specializzate che sostituiscono l'aggiunta manuale di UISwipeGestureRecognizer. Queste API supportano pulsanti di azione, animazione personalizzata e gesti "scorri per eliminare" — pattern standard nelle applicazioni mobili.

In iOS (11+), si usa UISwipeActionsConfiguration: il metodo tableView(_:leadingSwipeActionsConfigurationForRowAt:) restituisce un array di UIContextualAction — pulsanti con titolo, stile (destructive, normal) e gestore. Ad esempio, "Elimina" — .destructive con sfondo rosso, "Archivia" — .normal con sfondo grigio. Il sistema anima la comparsa dei pulsanti e chiama il blocco completion dopo un tocco.

In Android, ItemTouchHelper.SimpleCallback viene allegato a RecyclerView tramite ItemTouchHelper.attachToRecyclerView(). I parametri includono flag di direzione (start, end, up, down) e il callback onSwiped(viewHolder, direction). All'interno di onSwiped, viene chiamato adapter.notifyItemRemoved(position) per rimuovere l'elemento con animazione. ItemTouchHelper gestisce automaticamente i gesti, i conflitti di scorrimento e il ritorno dell'elemento se lo swipe non viene completato. Secondo Google I/O 2024, ItemTouchHelper è utilizzato nel 70% delle app Android con azioni di swipe nelle liste.

Esempi di codice in Swift e Kotlin

Esempio 1: Swipe a sinistra su iOS (Swift)

Aggiunge UISwipeGestureRecognizer a una vista per tornare alla schermata precedente. Il codice mostra la configurazione minima del riconoscitore con la direzione .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)
        }
    }
}

Il riconoscitore viene allegato alla vista radice del controller. Il controllo navigationController.viewControllers.count garantisce che pop venga eseguito solo quando è presente una schermata precedente nello stack. Per i controller modali, viene usato dismiss. Il codice non richiede controllo dello stato — UISwipeGestureRecognizer è discreto e chiama l'azione solo dopo il riconoscimento riuscito.

Esempio 2: Swipe in Android (Kotlin) con OnSwipeTouchListener personalizzato

Implementa un semplice wrapper di GestureDetector che determina la direzione dello swipe e chiama i callback 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 estende SimpleOnGestureListener, implementando onFling. diffX/diffY determinano la direzione, SWIPE_THRESHOLD (100px) e SWIPE_VELOCITY_THRESHOLD (100 px/s) sono le soglie. Utilizzo: view.setOnTouchListener(OnSwipeTouchListener(context).apply { onSwipeLeft = { dismiss() } }).

Esempio 3: SwipeActions in iOS (UITableView)

Aggiunge un pulsante di eliminazione quando si scorre a sinistra su una cella della tabella. Utilizza l'API integrata di iOS 11+ senza riconoscimento manuale dei gesti.

swift
func tableView(
    _ tableView: UITableView,
    trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath
) -> UISwipeActionsConfiguration? {
    let deleteAction = UIContextualAction(
        style: .destructive,
        title: "Elimina"
    ) { _, _, 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
}

Il metodo restituisce UISwipeActionsConfiguration con un array di UIContextualAction. style: .destructive imposta automaticamente lo sfondo rosso. performsFirstActionWithFullSwipe = true consente di eseguire l'azione con uno swipe completo senza tocco aggiuntivo. Presso IT Sectr, usiamo questa API per tutte le liste con azioni — è standardizzata, supporta VoiceOver e non richiede GestureRecognizer personalizzati.

Domande frequenti

Come distinguere uno swipe da una panoramica?

Lo swipe è un gesto discreto con movimento rapido e sollevamento del dito, la panoramica è un trascinamento continuo con tracciamento delle coordinate. UISwipeGestureRecognizer si attiva una volta, UIPanGestureRecognizer genera .began → .changed → .ended. La scelta dipende dallo scenario: swipe per azioni (eliminare, girare), pan per movimento (mappa, cursore).

Lo swipe funziona allo stesso modo su iOS e Android?

La logica del gesto è identica, ma l'API differisce. iOS usa UISwipeGestureRecognizer con direction. Android usa GestureDetector.onFling() con soglie personalizzate. Il risultato è la stessa UX con implementazioni diverse. I framework multipiattaforma (Flutter, React Native) astraggono la differenza attraverso un'API di swipe unificata.

Come gestire uno swipe in una lista?

In iOS (11+), usa UISwipeActionsConfiguration in UITableViewDelegate. In Android, usa ItemTouchHelper.SimpleCallback per RecyclerView. Queste API sostituiscono i GestureRecognizer manuali, supportano pulsanti di azione e animazione, gestiscono correttamente i conflitti di scorrimento e si adattano alle HIG della piattaforma.

Riepilogo

  • Lo swipe è un gesto discreto di scorrimento rapido del dito, il secondo più frequente dopo il tocco (23% delle interazioni).
  • In iOS, UISwipeGestureRecognizer gestisce gli swipe in quattro direzioni con una soglia fissa di ~20px.
  • In Android, GestureDetector.onFling() viene utilizzato con soglie personalizzate di velocità e distanza.
  • Per le liste, usa UISwipeActionsConfiguration (iOS) e ItemTouchHelper (Android) invece di riconoscitori manuali.
  • Lo swipe differisce dalla panoramica per discretezza e alta velocità — non confondere questi gesti durante la progettazione.
  • Un OnSwipeTouchListener personalizzato in Android semplifica l'API di GestureDetector nascondendo il calcolo della direzione.
  • Presso IT Sectr, usiamo lo swipe per navigazione, eliminazione di elementi e onboarding — il gesto è intuitivo e non richiede apprendimento.

Svilupperemo un'applicazione mobile chiavi in mano

IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.

Discuti il progetto

Leggi anche