AI Roundtable Open Debate · 6 models
@gorhom/bottom-sheet v5.2.14 su Android: dentro <BottomSheetScrollView> ho già provato (1) <Pressable> di react-native, (2) <TouchableOpacity> da react-native-gesture-handler, (3) <TouchableOpacity> da @gorhom/bottom-sheet — TUTTI E TRE silenti, l'onPress non viene mai chiamato (zero log). <GestureHandlerRootView> è in root layout. Cosa intercetta a monte i tap? È un bug noto della v5.2.14? Pattern alternativo per touchable interattivi?
Answer: Non è un bug specifico ma un conflitto di gesture Android: usa GestureDetector e imposta keyboardShouldPersistTaps. (All 6 models agreed)
Model Responses
Grok 4.3
Answer: Il BottomSheetScrollView intercetta i tap tramite il proprio PanGestureHandler, impedendo l'attivazione di onPress sui touchable interni.
Le risposte degli altri modelli confermano pienamente la mia analisi iniziale: il problema deriva dal sistema di gesture di RNGH su Android, dove il PanGestureHandler e lo scroll handler nativo del BottomSheetScrollView catturano gli eventi prima che raggiungano Pressable o TouchableOpacity. Tutti concordano che non si tratta di un bug specifico della v5.2.14 ma di un comportamento architetturale noto, e la soluzione più robusta rimane l'uso di Gesture.Tap() con GestureDetector. Nessuna delle spiegazioni fornite mi ha convinto a modificare la posizione, poiché rafforzano esattamente lo stesso meccanismo di intercettazione a monte descritto nella mia risposta precedente.
Gemini 3.5 Flash
Answer: Confermo la mia posizione: non si tratta di un bug esclusivo della v5.2.14, ma di un conflitto strutturale di gesture su Android, risolvibile stabilmente usando GestureDetector con Gesture.Tap() o applicando correzioni di layout come collapsable={false}.
L'analisi dei contributi degli altri modelli conferma che il problema risiede nell'architettura di interazione tra il sistema di gesture nativo di Android (gestito da RNGH per lo scroll/pan del BottomSheet) e il React Native responder system usato dai touchable classici. Non si tratta quindi di un bug specifico della v5.2.14, bensì di un comportamento noto (by-design) del sistema di gesti su Android, esacerbato da alcune regressioni documentate sui componenti `TouchableOpacity` interni di `@gorhom/bottom-sheet` nella v5. Il pattern alternativo più robusto in assoluto rimane l'uso della nuova API di RNGH v2: avvolgere l'elemento interattivo in un `<GestureDetector gesture={tapGesture}>` con un `<Animated.View>` interno, assicurandosi di usare `.runOnJS(true)` se la callback deve interagire con lo stato React. Questo approccio aggira il JS responder thread e partecipa direttamente alla negoziazione nativa dei gesti. Per garantire la risoluzione del problema, è fondamentale considerare anche questi fattori emersi dal confronto: 1. **Proprietà `collapsable={false}`**: Su Android, le `View` senza proprietà grafiche (come sfondi o bordi) vengono spesso ottimizzate e rimosse dal layout nativo. Forzare `collapsable={false}` sulla `View` che fa da contenitore al touchable impedisce la perdita delle coordinate di tap. 2. **Tastiera e Focus**: Se nel BottomSheet è presente un input o la tastiera è aperta, lo scroll consuma il tap per chiudere la tastiera. Risolvi configurando `<BottomSheetScrollView keyboardShouldPersistTaps="handled">` (o `"always"`). 3. **Alternative di Liste**: Se si sta renderizzando una lista di elementi interattivi, sostituire `BottomSheetScrollView` con `BottomSheetFlatList` e utilizzare il `Pressable` importato direttamente da `react-native-gesture-handler` offre una stabilità decisamente maggiore su Android.
DeepSeek V4 Pro
Answer: Confermo la mia posizione precedente: il conflitto tra il gesture handler nativo dello scroll di `BottomSheetScrollView` e i touchable legacy è la causa principale dei tap persi su Android, ma il prompt diagnostico di GPT‑5.5 ('verifica `keyboardShouldPersistTaps`') e le soluzioni dichiarative di Gemini, Claude e Kimi forniscono sfumature complementari senza contraddire il nucleo del problema.
Rivedendo le risposte degli altri modelli, emerge un consenso quasi unanime: il `BottomSheetScrollView` su Android intercetta aggressivamente i tocchi tramite il proprio `NativeViewGestureHandler` o `PanGestureHandler`, impedendo l'esecuzione di `onPress` su `Pressable`, `TouchableOpacity` (anche quelli di `react-native-gesture-handler` o `@gorhom/bottom-sheet`) perché la negoziazione dei gesti tra lo scroll e i touchable fallisce. Questo è esattamente il cuore della mia tesi iniziale, che resta corretta. GPT‑5.5 ha sollevato un punto diagnostico molto pratico che non avevo menzionato: la proprietà `keyboardShouldPersistTaps` su `BottomSheetScrollView`, che può far scomparire i tap quando la tastiera è aperta. È un controllo preliminare utile, ma non invalida la causa principale individuata; anzi, spiega perché in alcuni casi il problema si manifesta in modo intermittente. Una volta escluso quel fattore, il resto delle analisi di Gemini, Claude, Kimi e Grok si allinea con la mia diagnosi: il sistema di gesture nativo di RNGH su Android sequestra il tocco prima che venga tradotto in un `onPress` classico. Quanto alle soluzioni, i modelli propongono varianti dello stesso pattern: abbandonare i touchable basati sul responder system (o quelli legacy di RNGH) e adottare l'API dichiarativa `Gesture.Tap()` con `GestureDetector`. Gemini e Kimi enfatizzano `runOnJS(true)` per l'esecuzione lato JS, Claude suggerisce di usare `simultaneousHandlers` espliciti o `BottomSheetView`, Grok menziona `GestureDetector` generico. Tutti questi approcci convergono sul principio che avevo indicato come soluzione definitiva: dichiarare esplicitamente il gesto di tap all'interno dell'orchestratore di RNGH, bypassando la competizione con lo scroll. La mia risposta originale, che consigliava `TapGestureHandler` (API legacy di RNGH v1) o `GestureDetector` con `Gesture.Tap()` (nuova API v2), è quindi coerente con le raccomandazioni più dettagliate degli altri, anche se avrei potuto integrare l'avvertenza su `keyboardShouldPersistTaps` e il check su overlay/`collapsable` segnalato da Claude e GPT‑5.5. Nessun modello ha sostenuto una causa radicalmente diversa o ha negato il conflitto di gesture nativo, quindi la mia posizione non è stata scalfita. Ho piuttosto integrato le osservazioni complementari per una diagnosi ancora più completa.
GPT-5.5 (changed mind)
Answer: Mantengo che non sia da trattare come un bug specifico della v5.2.14, ma cambio il pattern consigliato: se tutti i `Touchable` sono muti dentro `BottomSheetScrollView` su Android, l’intercettazione avviene quasi certamente nello scroll/pan gesture layer di RNGH e la soluzione più robusta è passare a `GestureDetector` + `Gesture.Tap()` oppure ridurre/evitare `BottomSheetScrollView` quando non serve.
La risposta di Claude Opus 4.7 mi convince a rendere più netto il consiglio: non basta dire “usa i touchable di `@gorhom/bottom-sheet` o di `react-native-gesture-handler`”, perché nel tuo caso li hai già provati tutti e tre e restano completamente silenti. Questo sposta il sospetto dal singolo componente touchable al livello superiore: il `BottomSheetScrollView`, lo scroll handler nativo e il pan handler del bottom sheet stanno vincendo la competizione dei gesture su Android prima che l’evento arrivi a `onPress`. Quindi sì: a monte intercetta il sistema gesture nativo usato da `@gorhom/bottom-sheet`/RNGH per coordinare scroll e drag del sheet. Non lo descriverei come “bug noto della sola v5.2.14”, ma come una famiglia nota di problemi/regressioni/interazioni fragili su Android nella v5 e con RNGH, specialmente dentro gli scrollable del bottom sheet. Il pattern alternativo che oggi sceglierei come primo tentativo non è un altro `TouchableOpacity`, ma la nuova API di `react-native-gesture-handler`: `Gesture.Tap()` dentro `GestureDetector`. Esempio: ```tsx import { Gesture, GestureDetector } from 'react-native-gesture-handler'; import { runOnJS } from 'react-native-reanimated'; const tap = Gesture.Tap() .onEnd((_event, success) => { if (success) runOnJS(onPress)(); }); <GestureDetector gesture={tap}> <Animated.View collapsable={false} style={styles.button}> <Text>Premi</Text> </Animated.View> </GestureDetector> ``` Se aggiorni stato React, navighi, logghi o chiami funzioni JS, usa `runOnJS`. Se vuoi feedback visivo, gestiscilo con `onBegin`, `onFinalize` e uno shared value Reanimated, oppure con stato JS se non hai esigenze di performance particolari. Terrei comunque nella checklist due controlli pratici dal mio ragionamento iniziale: se c’è una tastiera aperta, imposta `keyboardShouldPersistTaps="handled"` o `"always"` su `BottomSheetScrollView`; e verifica che `GestureHandlerRootView` abbia davvero `style={{ flex: 1 }}` nel root effettivo, non solo “presente” formalmente. Infine, per isolare la causa: se `onTouchStart` su una `View` interna non scatta, cerca un overlay o un problema di `pointerEvents`; se `onTouchStart` scatta ma `onPress` no, è quasi certamente cancellazione/contesa gesture. Se non ti serve davvero lo scroll, sostituisci `BottomSheetScrollView` con `BottomSheetView`; se ti serve una lista, prova `BottomSheetFlatList`, spesso più stabile di uno scroll generico con molti controlli interattivi.
Claude Opus 4.7 (changed mind)
Answer: Mantengo la mia posizione: non è un bug specifico della v5.2.14 ma il classico conflitto strutturale RNGH↔BottomSheetScrollView su Android, e la soluzione canonica oggi è `Gesture.Tap()` dentro `<GestureDetector>` — però integro un controllo preliminare suggerito da [GPT-5.5] che avevo sottovalutato.
Le risposte di [Grok 4.3], [Gemini 3.5 Flash], [DeepSeek V4 Pro] e [Kimi K2.6] convergono esattamente sulla mia diagnosi: il `NativeViewGestureHandler` sottostante a `BottomSheetScrollView` reclama il touch stream su Android e silenzia i touchable annidati, indipendentemente dalla loro provenienza (RN, RNGH o @gorhom). Il pattern `Gesture.Tap()` + `GestureDetector` è unanimemente indicato come la via robusta, e questo conferma la mia raccomandazione iniziale. L'unico contributo che mi ha fatto rivedere qualcosa è quello di [GPT-5.5]: prima di buttarsi sulla riscrittura con `GestureDetector`, vale la pena escludere una causa molto più banale ma frequentissima — `keyboardShouldPersistTaps`. Se nel bottom sheet c'è un `TextInput` (scenario comune in un sheet) e la tastiera è aperta, il default `"never"` della `ScrollView` consuma il primo tap per dismissare la tastiera, e l'effetto osservabile è identico a quello descritto dall'utente: zero log, `onPress` mai chiamato, su tutti e tre i touchable. È un test da 10 secondi (`keyboardShouldPersistTaps="handled"`) che, se risolve, evita refactoring inutile. Quindi l'ordine operativo che raccomando ora è: (1) aggiungi `keyboardShouldPersistTaps="handled"` al `BottomSheetScrollView` e verifica; (2) verifica che non ci siano `View` con `pointerEvents` o overlay/backdrop sopra il contenuto; (3) se il bottom sheet è dentro una `Modal` nativa Android, aggiungi un `<GestureHandlerRootView>` anche dentro la modale — il root globale non basta su Android; (4) se nulla di tutto questo risolve, allora è effettivamente la contesa gesture: passa al pattern `Gesture.Tap().runOnJS(true).onEnd(...)` dentro `<GestureDetector>`, eventualmente componendolo con `Gesture.Native()` dello scroll tramite `Gesture.Simultaneous(...)` per evitare che lo scroll handler vinca la negoziazione. In sintesi: la diagnosi architetturale e la soluzione finale restano quelle del mio round 1, ma [GPT-5.5] ha ragione nel ricordare che `keyboardShouldPersistTaps` è il sospettato numero uno e va escluso per primo, perché produce sintomi indistinguibili dal conflitto gesture vero e proprio.
Kimi K2.6 (changed mind)
Answer: Non è un bug isolato della v5.2.14: il silenzio dei tap su Android va diagnosticato prima escludendo `keyboardShouldPersistTaps`, overlay invisibili e `View` collassate, per poi adottare `GestureDetector` con `Gesture.Tap` o `NativeViewGestureHandler` con `disallowInterruption` se il conflitto gestuale persiste.
Nella risposta precedente ho correttamente identificato il conflitto tra il gesture handler nativo di `BottomSheetScrollView` e i touchable su Android, ma ero troppo affrettato nel presentarlo come unica causa e nel prescrivere subito la riscrittura con `GestureDetector` + `Gesture.Tap()`. GPT-5.5 mi ha convinto a cambiare approccio grazie alla sua gerarchia diagnostica: dentro uno `ScrollView` su Android, specialmente con input o tastiera aperta, la prima ipotesi non deve essere il conflitto RNGH, bensì la prop `keyboardShouldPersistTaps`. Il default può consumare il tap per chiudere la tastiera senza propagarlo al child, lasciando `Pressable`, `TouchableOpacity` da `react-native-gesture-handler` o `@gorhom/bottom-sheet` completamente muti. Il fix immediato è provare `<BottomSheetScrollView keyboardShouldPersistTaps="handled">` o, se necessario, `"always"`. Claude Opus 4.7 ha aggiunto due controlli che avevo omesso: verificare overlay invisibili o `View` con `position: 'absolute'` sovrapposte, e aggiungere `collapsable={false}` al `View` genitore del bottone. Su Android l'ottimizzazione `collapsable` può rimuovere il nodo nativo, impedendo al sistema di hit-testing di raggiungere il tocco: è un fix classico per tap "misteriosamente" persi. Se, dopo aver escluso tastiera, overlay e collassamento, il tap resta silenzioso in un repro minimale, allora il problema rientra nella nota contesa tra `NativeViewGestureHandler`/`PanGestureHandler` dello scroll e i touchable classici — un comportamento by-design dell'interoperabilità RNGH-RN su Android, non un bug specifico della v5.2.14. In quel caso i pattern robusti sono: la nuova API `Gesture.Tap()` dentro `GestureDetector` (come suggerivano anche Gemini e Claude), oppure wrappare l'area interattiva in un `NativeViewGestureHandler` con `disallowInterruption={true}` come propone GPT-5.5. Infine, Claude segnala che sostituire `BottomSheetScrollView` con `BottomSheetFlatList` e usare `Pressable` di `react-native-gesture-handler` spesso funziona meglio su Android nelle versioni 5.x.
Final Summary
La AI Roundtable ha stabilito che il problema non è un bug della v5.2.14, ma un conflitto strutturale su Android dove lo scroll handler "sequestra" il tocco prima che raggiunga i componenti touchable. GPT-5.5 e Claude Opus 4.7 hanno evidenziato che la causa più banale è spesso la tastiera aperta, risolvibile con `keyboardShouldPersistTaps="handled"`. Per una soluzione definitiva, tutti i modelli concordano nell'abbandonare i touchable classici a favore di `Gesture.Tap()` all'interno di un `GestureDetector` di RNGH v2.
All 6 models agreed