La Navigazione Gestuale è un sistema per controllare un'applicazione mobile attraverso gesti tattili, che ha sostituito i pulsanti hardware sulla maggior parte degli smartphone moderni. Secondo Android Developers (2024), la navigazione gestuale è diventata lo standard a partire da Android 10, mentre Apple è passata ai gesti con l'iPhone X nel 2017. Il sistema include scorrimento, pizzicamento, doppio tocco e pressione lunga — ogni gesto ha uno scopo specifico nel contesto dello schermo. Comprendere l'architettura della navigazione gestuale è essenziale per creare interfacce intuitive e reattive.
Punti Chiave
La Navigazione Gestuale è un metodo di interazione dell'utente con un dispositivo mobile attraverso sequenze di tocchi, movimenti e pressioni riconosciute dal touch screen. A differenza dei pulsanti tradizionali, i gesti non hanno una posizione fissa sullo schermo e vengono riconosciuti da modelli di movimento: scorrimento dal bordo, pizzicamento con due dita, pressione lunga.
La transizione alla navigazione gestuale è iniziata con l'iPhone X (2017), quando Apple ha rimosso completamente il pulsante Home, sostituendolo con uno scorrimento dal bordo inferiore. Google ha seguito la tendenza con Android 10 (2020), offrendo agli utenti la scelta: navigazione a tre pulsanti, navigazione a due pulsanti e navigazione gestuale completa. Secondo StatCounter (2025), oltre il 75% dei dispositivi Android e il 95% dei dispositivi iOS utilizza la navigazione gestuale.
Architettonicamente, il riconoscimento dei gesti si compone di tre fasi: Acquisizione (cattura degli eventi tattili), Riconoscimento (identificazione del modello di movimento) e Azione (esecuzione dell'azione assegnata). A livello di sistema, Android e iOS dispongono di gestori integrati per i gesti di navigazione di base — scorrimento indietro, andare alla schermata home, aprire il commutatore di app. Lo sviluppatore deve solo integrare correttamente i propri gesti in questo sistema.
Tutti i gesti tattili possono essere suddivisi in tre categorie in base allo scopo e al metodo di esecuzione. Ogni tipo ha le proprie regole di elaborazione e raccomandazioni per l'uso nell'interfaccia.
I gesti di navigazione controllano lo spostamento tra schermate: scorrimento dal bordo sinistro per tornare indietro (iOS), scorrimento verso l'alto per aprire il commutatore di app, scorrimento dal bordo inferiore per tornare alla schermata home. Questi gesti vengono elaborati dal sistema a livello di finestra e non dovrebbero entrare in conflitto con i gesti personalizzati all'interno dell'app.
I gesti di manipolazione modificano la posizione, le dimensioni o l'orientamento degli oggetti sullo schermo. Pizzicamento (zoom a due dita), rotazione, trascinamento, scorrimento rapido — tutti questi gesti vengono elaborati a livello di View o Composable e non influenzano la navigazione di sistema.
I gesti contestuali attivano funzioni aggiuntive senza navigare verso un'altra schermata. Pressione lunga (per menu contestuale), doppio tocco (per like o zoom), scorrimento dal bordo (per aprire un Drawer). Questi gesti richiedono l'implementazione più attenta poiché possono sovrapporsi ai gesti di navigazione di sistema.
| Tipo di Gesto | Esempio | Livello di Elaborazione | Conflitto di Sistema |
|---|---|---|---|
| Navigazione | Scorrimento indietro | Window / Sistema | Primario |
| Manipolazione | Pizzicamento zoom | View | No |
| Contestuale | Pressione lunga | View | Possibile |
Android SDK fornisce un sistema di elaborazione dei gesti a più livelli, dal MotionEvent di basso livello al GestureDetector e GestureOverlayView di alto livello. La scelta del livello corretto dipende dalla complessità del gesto e dai requisiti di prestazione.
GestureDetector è una classe di alto livello che converte una sequenza di MotionEvent in gesti specifici: onDown, onShowPress, onSingleTapUp, onScroll, onLongPress, onFling. Lo sviluppatore sovrascrive i metodi necessari di GestureDetector.SimpleOnGestureListener e riceve un evento riconosciuto pronto. GestureDetector è raccomandato per tutti i gesti standard tranne il ridimensionamento — per quello esiste ScaleGestureDetector.
val gestureDetector = GestureDetector(this, object : GestureDetector.SimpleOnGestureListener() {
override fun onFling(
e1: MotionEvent?, e2: MotionEvent,
velocityX: Float, velocityY: Float
): Boolean {
val deltaX = e2.x - (e1?.x ?: 0f)
return if (Math.abs(deltaX) > Math.abs(e2.y - (e1?.y ?: 0f))) {
if (deltaX > 0) onSwipeRight() else onSwipeLeft()
true
} else false
}
})
view.setOnTouchListener { _, event -> gestureDetector.onTouchEvent(event) }
TouchDelegate è un meccanismo per estendere l'area tattile di una View. Viene utilizzato quando l'elemento target è più piccolo della dimensione tattile minima di 48dp. Ad esempio, un piccolo pulsante "Chiudi" nell'angolo dello schermo riceve un TouchDelegate che estende la sua area di impatto senza modificare la dimensione visibile. Google raccomanda TouchDelegate per tutti gli elementi interattivi più piccoli di 48x48dp.
Compose fornisce modificatori per la gestione dei gesti: clickable, draggable, swipeable, combinedClickable (per doppio tocco e pressione lunga). Internamente, Compose utilizza PointerInputScope per l'elaborazione di basso livello, ma la maggior parte degli sviluppatori ha bisogno solo dei modificatori di alto livello. Per gesti personalizzati, utilizzare pointerInput con awaitPointerEvent.
iOS SDK utilizza l'architettura UIGestureRecognizer — una classe base astratta che analizza una sequenza di UITouch e determina se corrisponde a un gesto noto. Apple raccomanda di utilizzare riconoscitori standard quando possibile e di creare sottoclassi personalizzate solo per gesti unici.
UIKit fornisce un insieme di riconoscitori pronti all'uso: UITapGestureRecognizer, UISwipeGestureRecognizer, UIPanGestureRecognizer, UIPinchGestureRecognizer, UIRotationGestureRecognizer, UILongPressGestureRecognizer. Ogni riconoscitore ha stati (possible, began, changed, ended, cancelled, failed) — lo sviluppatore traccia lo stato per reagire in diverse fasi del gesto.
let swipeBack = UISwipeGestureRecognizer(
target: self,
action: #selector(handleSwipeBack)
)
swipeBack.direction = .right
view.addGestureRecognizer(swipeBack)
@objc func handleSwipeBack() {
navigationController?.popViewController(animated: true)
}
SwiftUI utilizza modificatori di gesti dichiarativi, simili a Compose: onTapGesture, onLongPressGesture, MagnificationGesture, RotationGesture, DragGesture. SwiftUI gestisce automaticamente i conflitti tra gesti attraverso simultaneousGesture, sequencedGesture e exclusiveGesture — modificatori che determinano la priorità del gesto quando attivati simultaneamente.
Image("photo")
.gesture(
MagnificationGesture()
.onChanged { scale in
self.currentScale = scale
}
.sequenced(before: DragGesture())
)
InteractivePopGestureRecognizer è un riconoscitore di sistema che controlla il gesto di scorrimento indietro in UINavigationController. Per impostazione predefinita, è attivo per tutte le schermate tranne la radice. Se la tua app utilizza una NavigationBar personalizzata, interactivePopGestureRecognizer potrebbe smettere di funzionare — sarà necessario attivarlo programmaticamente tramite navigationController.interactivePopGestureRecognizer?.delegate.
Il conflitto di gesti è uno dei problemi più difficili nella navigazione gestuale. Quando un gesto personalizzato (ad esempio, aprire un Drawer scorrendo dal bordo sinistro) coincide con un gesto di sistema (scorrimento indietro su iOS o Android), il sistema deve determinare quale gesto ha priorità. Gestire correttamente questo conflitto è fondamentale per l'esperienza utente.
Android 10+ consente all'app di riservare aree dello schermo per i propri gesti tramite WindowInsets. Utilizzare ViewCompat.setSystemGestureExclusionRects per specificare le regioni in cui i gesti di sistema non devono attivarsi. Ad esempio, per un Drawer a sinistra, è possibile escludere il bordo sinistro dello schermo (fino a 200dp di larghezza) dallo scorrimento indietro di sistema. Google ha fissato un limite: fino a 200dp possono essere esclusi per ogni lato.
val exclusionRect = Rect(0, 0, 200, height)
ViewCompat.setSystemGestureExclusionRects(
drawerView,
listOf(SystemGestureExclusionRect(exclusionRect))
)
iOS fornisce il metodo gestureRecognizerShouldBegin in UIGestureRecognizerDelegate, che consente a un riconoscitore personalizzato di decidere se iniziare il riconoscimento. Per uno scorrimento di Drawer dal bordo sinistro, è possibile controllare la posizione del tocco: se l'utente sta trascinando il Drawer (la distanza supera la soglia), il gesto personalizzato prende il controllo. Se il gesto non viene riconosciuto, il sistema restituisce il controllo a InteractivePopGestureRecognizer.
La Navigazione Gestuale richiede una progettazione attenta, specialmente sui dispositivi con navigazione gestuale di sistema. Esaminiamo gli errori comuni e le raccomandazioni per risolverli.
L'errore più comune è posizionare elementi interattivi o implementare scorrimenti personalizzati nelle zone dei gesti di sistema (bordi sinistro e destro, bordo inferiore). L'utente tenta di eseguire un'azione, ma invece si attiva la navigazione di sistema. Fornire sempre margini per i gesti di sistema e gestire i conflitti tramite exclusion rects.
I parametri dei gesti (soglia di velocità, distanza minima) differiscono per impostazione predefinita tra le piattaforme. Se la tua app è multipiattaforma, non copiare i parametri da una piattaforma all'altra — testare ogni gesto separatamente su Android e iOS. Flutter e React Native adattano automaticamente alcuni parametri, ma non tutti.
Ogni gesto dovrebbe essere accompagnato da feedback visivo: cambio di colore, trasformazione, animazione. L'utente deve capire che il gesto è stato riconosciuto e l'azione è in esecuzione. Su iOS, i riconoscitori di sistema forniscono automaticamente feedback aptico; su Android deve essere aggiunto tramite HapticFeedbackConstants.
Non tutti gli utenti possono eseguire gesti — le persone con capacità motorie limitate utilizzano VoiceOver e TalkBack per la navigazione. Ogni gesto dovrebbe avere un'alternativa tramite pulsante. Google e Apple richiedono che tutte le azioni gestuali siano duplicate con controlli disponibili per l'accessibilità.
Domande Frequenti
iOS — Apple ha introdotto la navigazione gestuale con l'iPhone X nel 2017, sostituendo il pulsante Home con uno scorrimento dal bordo inferiore. Android ha seguito l'esempio con Android 10 (2020), offrendo i gesti come alternativa ai pulsanti.
Scorrimento è un movimento veloce con alta velocità (px/s) ed è intermittente. Scroll è un movimento lento con bassa velocità ed è continuo. Utilizzare velocityX/Y per distinguere: la soglia è tipicamente 500—1000 px/s a seconda della piattaforma.
No — Android e iOS non consentono a un'app di disabilitare la navigazione gestuale di sistema. Puoi solo riservare aree dello schermo tramite exclusion rects (Android) o gestureRecognizerShouldBegin (iOS).
Android Emulator supporta il multitouch tramite Ctrl+clic (aggiunta di un secondo dito). Il Simulatore iOS utilizza Option+clic per due dita. Flutter test utilizza WidgetTester.timedDrag per simulare scorrimenti nei test unitari.
Gesture War è un conflitto tra due riconoscitori quando entrambi cercano di elaborare lo stesso tocco. Evitarlo tramite priorità: in iOS utilizzare require(toFail:), in Compose utilizzare sequentialGesture e exclusiveGesture. Flutter utilizza GestureArena per la risoluzione automatica.
Riepilogo
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.
Leggi anche