Title: Improve gestures to allow for cancellation, interception and customizability · Issue #7310 · NativeScript/NativeScript · GitHub
Open Graph Title: Improve gestures to allow for cancellation, interception and customizability · Issue #7310 · NativeScript/NativeScript
X Title: Improve gestures to allow for cancellation, interception and customizability · Issue #7310 · NativeScript/NativeScript
Description: Is your feature request related to a problem? Please describe. Currently, there is no way to cancel or intercept a gesture. Example: if you set a tap to a child and a parent, both will trigger. Custom gestures must also be handled manual...
Open Graph Description: Is your feature request related to a problem? Please describe. Currently, there is no way to cancel or intercept a gesture. Example: if you set a tap to a child and a parent, both will trigger. Cus...
X Description: Is your feature request related to a problem? Please describe. Currently, there is no way to cancel or intercept a gesture. Example: if you set a tap to a child and a parent, both will trigger. Cus...
Opengraph URL: https://github.com/NativeScript/NativeScript/issues/7310
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"Improve gestures to allow for cancellation, interception and customizability","articleBody":"**Is your feature request related to a problem? Please describe.**\r\nCurrently, there is no way to cancel or intercept a gesture. Example: if you set a `tap` to a child and a parent, both will trigger. Custom gestures must also be handled manually with `touch` events.\r\n\r\nMore often than not, when using `tap`, you just want one `tap` to trigger. Say you have a card and an user picture inside the card. If you tap anywhere on the card you want to open a URL or show more details about the card, if you tap on the user picture, you want to show the user profile. Currently this completely breaks in {N} and requires workarounds, while works out of the box (and is the default behavior) in other frameworks. This makes developing complex UIs frustrating and actually recudes the usability of `TappableSpan`s #7076, since you can't reliably create a `tap` for a URL and another for the text, for example. If you check apps like Facebook and Instagram, this is used absolutely everywhere.\r\n\r\n**Describe the solution you'd like**\r\nA Gesture Arena with `HitTestBehavior` and `AllowMultipleGestureRecognizer`, similar to Flutter (https://medium.com/flutter-community/flutter-deep-dive-gestures-c16203b3434f), but allowing better bubbling (it seems flutter does not allow for two events of the same kind to be trigger simultaneously, like parent and child `tap`).\r\n\r\nThe current {N} implementation is like `AllowMultipleGestureRecognizer = true` and `HitTestBehavior = translucent`, but with the added factor that no event is unique. Multiple gestures are recognized loosely and they all bubble to the parents.\r\n\r\nIdeally, we should be able to set additional properties to each event of a view (`tap`, `drag`, etc), register our own gesture recognizers (like a raw gesture that returns true when recognized), and generate relations between them (custom gesture can't trigger along with child/parent `swipe`, or child `tap` has precedence over parent `tap` or vice-versa, for example).\r\n\r\nHonestly, any implementation that allows the user to eat an event type would work better than the current bubbling.\r\n\r\n**Describe alternatives you've considered**\r\nUsing booleans to detect child events and gesture detection and discard events when needed. This adds a lot of complexity in the UI code.\r\n\r\n**Additional context**\r\n\r\nI've already done some research on the possible implications and implementations. Maybe we could work on a proper API proposal.\r\n\r\n**iOS:**\r\n\r\nCurrently, we're already running all recognizers simulaneously. This behavior can be expanded to add relations. Since we have `owner` references, we should be able to get these dynamically for the view (https://developer.apple.com/documentation/uikit/touches_presses_and_gestures/coordinating_multiple_gesture_recognizers)\r\n https://github.com/NativeScript/NativeScript/blob/7d3f0d9e96976d257b17f9019ea0d101b827572f/tns-core-modules/ui/gestures/gestures.ios.ts#L18-L20\r\n\r\nUsing the same `owner` references, we could also do the same when deciding for exclusivity, or discarding similar events if that's what the view wants\r\n(https://developer.apple.com/documentation/uikit/touches_presses_and_gestures/coordinating_multiple_gesture_recognizers/preferring_one_gesture_over_another)\r\n\r\n**Android:**\r\n\r\nEvery `touchable` view on android returns `true` on `onTouchEvent`, so the event is always intercepted by the furthest child in the chain (http://codetheory.in/understanding-android-input-touch-events/). {N} solves this via an undocumented breaking change of NS 5.0 (mistakenly opened as #6606) in which all `MotionEvent`s bubble up to their parents indiscriminately.\r\n\r\nhttps://github.com/NativeScript/NativeScript/blob/cf533a7b6d6607aefd39c06978578bb2b453eb3d/tns-core-modules/ui/core/view/view.android.ts#L397-L399\r\n\r\n\r\nThis behavior can be solved in Android by passing additional data up the chain, like what events were triggered by the `MotionEvent`. `android.view.GestureDetector` triggers them synchronously, so we could store a `triggered` variable that sets itself when an event has been triggered, which is later reset by the `GesturesObserver` which is handling it.\r\n\r\nhttps://github.com/NativeScript/NativeScript/blob/05c2460fc4989dae4d7fa1ee52f6d54e0c3113f5/tns-core-modules/ui/gestures/gestures.android.ts#L333-L335\r\n\r\n```\r\nif(this._simpleGestureDetector.triggeredEvent) {\r\ntriggeredEvents.push(this._simpleGestureDetector.triggeredEvent);\r\nthis._simpleGestureDetector.triggeredEvent = null;\r\n}\r\n...\r\n// check triggeredEvents self dependency\r\n// trigger exclusive events (that can't be bubbled up)\r\n// bubble up events that can be bubbled up\r\n// on the topmost (activity) actually trigger all events that were queued\r\n```\r\n\r\nPossible edge case: parent wants to intercept event but child doesn't want bubbling.\r\n\r\n\r\n\u003cbountysource-plugin\u003e\r\n\r\n---\r\nWant to back this issue? **[Post a bounty on it!](https://www.bountysource.com/issues/75078809-improve-gestures-to-allow-for-cancellation-interception-and-customizability?utm_campaign=plugin\u0026utm_content=tracker%2F12908224\u0026utm_medium=issues\u0026utm_source=github)** We accept bounties via [Bountysource](https://www.bountysource.com/?utm_campaign=plugin\u0026utm_content=tracker%2F12908224\u0026utm_medium=issues\u0026utm_source=github).\r\n\u003c/bountysource-plugin\u003e","author":{"url":"https://github.com/edusperoni","@type":"Person","name":"edusperoni"},"datePublished":"2019-06-04T22:50:28.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":1},"url":"https://github.com/7310/NativeScript/issues/7310"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:d3f6120e-b0a8-5502-e160-667ae200292d |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | EA94:67DD8:87F5817:BA559A2:6973A6AA |
| html-safe-nonce | e0b87ad66178172eced07ea27c61748c10fa40c28e0aad3dcb878ae29aaa7e4c |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJFQTk0OjY3REQ4Ojg3RjU4MTc6QkE1NTlBMjo2OTczQTZBQSIsInZpc2l0b3JfaWQiOiI2MDQ4ODk4NTkxMzEwOTgwNzc4IiwicmVnaW9uX2VkZ2UiOiJpYWQiLCJyZWdpb25fcmVuZGVyIjoiaWFkIn0= |
| visitor-hmac | fe589b30c86086932c9afaf58e8302465c0ddf90cd161dcd6fed91b3ce824dbc |
| hovercard-subject-tag | issue:452241581 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/NativeScript/NativeScript/7310/issue_layout |
| twitter:image | https://opengraph.githubassets.com/1adaa2c6507c2e7d5a1e1c834d1a8a3336b0a488e6cc981c50fb9d52ff3a043c/NativeScript/NativeScript/issues/7310 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/1adaa2c6507c2e7d5a1e1c834d1a8a3336b0a488e6cc981c50fb9d52ff3a043c/NativeScript/NativeScript/issues/7310 |
| og:image:alt | Is your feature request related to a problem? Please describe. Currently, there is no way to cancel or intercept a gesture. Example: if you set a tap to a child and a parent, both will trigger. Cus... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | edusperoni |
| hostname | github.com |
| expected-hostname | github.com |
| None | 3e9aa9d0c22a21b13b378b4acd09f5dd4876a884425aacd32a9f473b84c8762d |
| turbo-cache-control | no-preview |
| go-import | github.com/NativeScript/NativeScript git https://github.com/NativeScript/NativeScript.git |
| octolytics-dimension-user_id | 7392261 |
| octolytics-dimension-user_login | NativeScript |
| octolytics-dimension-repository_id | 31492490 |
| octolytics-dimension-repository_nwo | NativeScript/NativeScript |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 31492490 |
| octolytics-dimension-repository_network_root_nwo | NativeScript/NativeScript |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | ae4dbd3ac4179af799d71b75a60b0075ccccc5f6 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width