Closed borjandev closed 2 weeks ago
@chunhtai @Renzo-Olivares @xu-baolin @justinmc This seems to be caused by https://github.com/flutter/flutter/pull/123055
Since that pull request landed in master, and I assume passed your internal checks and tests, does that mean that this is intended behaviour?
If it is indeed intended, then is there some simple parameter that we can change in the Dismissible or the TextField widget in order to make the Dismissible win the GestureArena ?
Essentially the way that it was working before commit 90f8ac5b41129a21878fe1607a9fcf57576a840c was merged?
Thank you for reporting this @borjandev. Getting this behavior correct is really tricky since text selection dragging gestures on mobile devices were just recently introduced (they have been supported on desktop for a while). What you can do for now as a short-term solution is wrap your Dismissible
in a MediaQuery
with a custom gestureSettings
like the code sample below.
What this does is changes the drag acceptance threshold for touch devices for the Dismissible
making it 0.1
(by default it is 8.0
) lower than the drag acceptance threshold of the TextField
for touch devices which is also 8.0
by default. This way Dismissible
can always beat the TextField
.
The side-effects of this is that text selection dragging gestures will not work inside of the TextField
that is within the Dismissible
because it will always win. Regular tap gestures, and long press gestures will still work inside of that TextField
.
I'll see if I can come up with a better solution / decide if this behavior is expected for this type of use case, but a full solution might be tricky given the constraints. Curious to hear others thoughts.
Edit: Updated context on the issue: https://github.com/flutter/flutter/issues/127017#issuecomment-1564992595
@Renzo-Olivares Thank you for the prompt response, and for the short-term solution!
Modifying the touchSlop is viable in my use case.
Looking forward to hear thoughts from others, but feel free to close this issue if needed, as even in the absence of an ideal full solution, I would accept the tradeoff of needing to modify the touchSlop, as it provides the necessary control to prioritise the widget which wins the GestureArena, which can be tailored to the specific app use case.
Great to hear that worked for you! I'll keep this open for discussion, and at the least I think I'll probably make a PR to add this use-case to the documentation somewhere so it is more discoverable to others.
This is replicable on latest master but not on latest stable.
Code sample: https://github.com/flutter/flutter/issues/124421#issue-1659166549
Note: I didn't add regression
label to this based on below comment as it looks like the recently introduced functionality specially on mobile devices is causing the reported behavior.
Getting this behavior correct is really tricky since text selection dragging gestures on mobile devices were just recently introduced (they have been supported on desktop for a while). What you can do for now as a short-term solution is wrap your
Dismissible
in aMediaQuery
with a customgestureSettings
like the code sample below.
Hey @Renzo-Olivares,
Thanks for introducing this workaround, I believe I have a different case but is also related to this issue.
Currently when having a ListView and putting the scrollDirection
to horizontal and adding a TextField as the child, the Textfield will no longer be draggable.
This problem strangely only occurs on IOS and not on Android. I would love to know if there is a similar work around for this use-case.
Thank you.
@Sembauke can you post a code sample? Thank you
Responding here, despite not being related to TextField, because https://github.com/flutter/flutter/issues/127165 was closed in favor of this ticket.
On iOS, you can no longer (as of 3.10) trigger certain GestureDetectors on SelectableText. For instance, onHorizontalDragUpdate will not trigger if you swipe right on the text in the below code sample. However, if that ListView is still flinging/scrolling then it will indeed trigger. I included a lot of text so you can play with the vertical scrolling. If it's idle then the GestureDetector doesn't work, if it's ScrollDirection.forward or ScrollDirection.reverse then it does work.
import 'package:flutter/material.dart';
class TermsScreen extends StatelessWidget {
const TermsScreen({super.key});
@override
Widget build(BuildContext context) {
return GestureDetector(
onHorizontalDragUpdate: (DragUpdateDetails dragUpdateDetails) {
if (dragUpdateDetails.delta.dx > 20) {
Navigator.pop(context);
}
},
child: Scaffold(
body: Container(
padding: const EdgeInsets.symmetric(horizontal: 24.0),
child: ListView(
children: const <Widget>[
SelectableText.rich(
TextSpan(
style: TextStyle(color: Colors.black, fontSize: 17.0),
children: [
TextSpan(
text: "Notice that widgets are passed as arguments to other widgets. The Scaffold widget takes a number of different widgets as named arguments, each of which are placed in the Scaffold layout in the appropriate place. Similarly, the AppBar widget lets you pass in widgets for the leading widget, and the actions of the title widget. This pattern recurs throughout the framework and is something you might consider when designing your own widgets.",
style: TextStyle(color: Colors.black, fontSize: 17.0),
),
TextSpan(
text: "Notice that widgets are passed as arguments to other widgets. The Scaffold widget takes a number of different widgets as named arguments, each of which are placed in the Scaffold layout in the appropriate place. Similarly, the AppBar widget lets you pass in widgets for the leading widget, and the actions of the title widget. This pattern recurs throughout the framework and is something you might consider when designing your own widgets.",
style: TextStyle(color: Colors.black, fontSize: 17.0),
),
TextSpan(
text: "Notice that widgets are passed as arguments to other widgets. The Scaffold widget takes a number of different widgets as named arguments, each of which are placed in the Scaffold layout in the appropriate place. Similarly, the AppBar widget lets you pass in widgets for the leading widget, and the actions of the title widget. This pattern recurs throughout the framework and is something you might consider when designing your own widgets.",
style: TextStyle(color: Colors.black, fontSize: 17.0),
),
TextSpan(
text: "Notice that widgets are passed as arguments to other widgets. The Scaffold widget takes a number of different widgets as named arguments, each of which are placed in the Scaffold layout in the appropriate place. Similarly, the AppBar widget lets you pass in widgets for the leading widget, and the actions of the title widget. This pattern recurs throughout the framework and is something you might consider when designing your own widgets.",
style: TextStyle(color: Colors.black, fontSize: 17.0),
),
TextSpan(
text: "Notice that widgets are passed as arguments to other widgets. The Scaffold widget takes a number of different widgets as named arguments, each of which are placed in the Scaffold layout in the appropriate place. Similarly, the AppBar widget lets you pass in widgets for the leading widget, and the actions of the title widget. This pattern recurs throughout the framework and is something you might consider when designing your own widgets.",
style: TextStyle(color: Colors.black, fontSize: 17.0),
),
TextSpan(
text: "Notice that widgets are passed as arguments to other widgets. The Scaffold widget takes a number of different widgets as named arguments, each of which are placed in the Scaffold layout in the appropriate place. Similarly, the AppBar widget lets you pass in widgets for the leading widget, and the actions of the title widget. This pattern recurs throughout the framework and is something you might consider when designing your own widgets.",
style: TextStyle(color: Colors.black, fontSize: 17.0),
),
],
),
),
],
),
),
),
);
}
}
@Sembauke can you post a code sample? Thank you
@Renzo-Olivares We got it working with your workaround. Thanks
Looks like the workaround stopped working after recent flutter updates. Any update on this? Does this workaround work for you on the latest stable Flutter?
@Renzo-Olivares can you help here?
This issue is assigned to @Renzo-Olivares but has had no recent status updates. Please consider unassigning this issue if it is not going to be addressed in the near future. This allows people to have a clearer picture of what work is actually planned. Thanks!
@Renzo-Olivares this needs flutter team's attention
Just adding my comment here that this is causing me issues as well. Does the flutter team have a work around here that we could use considering the above workaround does not work anymore? Is a fix incoming?
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v
and a minimal reproduction of the issue.
Steps to Reproduce
flutter run
on the code sampleExpected results: TextField is horizontally draggable, text inside TextField changes to "Wee.. I'm being dragged"
Actual results: TextField is not horizontally draggable, text inside TextField is still "Drag me horizontally"
Code sample
```dart import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; const defaultText = "Drag me horizontally"; const successText = "Wee.. I'm being dragged"; final dismissibleTextEditingController = TextEditingController(text: defaultText); void main() { debugPrintGestureArenaDiagnostics = true; runApp( MaterialApp( home: Scaffold( body: Container( padding: const EdgeInsets.all(50), child: Center( child: Dismissible( direction: DismissDirection.horizontal, onUpdate: (details) { dismissibleTextEditingController.text = successText; if (details.progress == 0.0) { dismissibleTextEditingController.text = defaultText; } }, key: const Key('Dismissible'), child: TextField( controller: dismissibleTextEditingController, ), ), ), ), ), ), ); } ```Logs
Successful Gesture Arena on a690c0485f8afc6200f8d1dc60e483aeed8f01a7. ``` flutter: Gesture arena 3 ❙ ★ Opening new gesture arena. flutter: Gesture arena 3 ❙ Adding: LongPressGestureRecognizer#6412b(debugOwner: _TextSelectionGestureDetectorState#09cd1, state: ready) flutter: Gesture arena 3 ❙ Adding: TapAndDragGestureRecognizer#a9a43(debugOwner: _TextSelectionGestureDetectorState#09cd1) flutter: Gesture arena 3 ❙ Adding: HorizontalDragGestureRecognizer#f173b(debugOwner: GestureDetector, start behavior: start) flutter: Gesture arena 3 ❙ Closing with 3 members. flutter: Gesture arena 3 ❙ Rejecting: LongPressGestureRecognizer#6412b(debugOwner: _TextSelectionGestureDetectorState#09cd1, state: possible) flutter: Gesture arena 3 ❙ Accepting: HorizontalDragGestureRecognizer#f173b(debugOwner: GestureDetector, start behavior: start) flutter: Gesture arena 3 ❙ Self-declared winner: HorizontalDragGestureRecognizer#f173b(debugOwner: GestureDetector, start behavior: start) ``` Unsuccessful Gesture Arena on commit 90f8ac5b41129a21878fe1607a9fcf57576a840c and subsequent commits ``` flutter: Gesture arena 1 ❙ ★ Opening new gesture arena. flutter: Gesture arena 1 ❙ Adding: LongPressGestureRecognizer#fec4e(debugOwner: _TextSelectionGestureDetectorState#1676e, state: ready) flutter: Gesture arena 1 ❙ Adding: TapAndHorizontalDragGestureRecognizer#dc538(debugOwner: _TextSelectionGestureDetectorState#1676e) flutter: Gesture arena 1 ❙ Adding: HorizontalDragGestureRecognizer#2bb6b(debugOwner: GestureDetector, start behavior: start) flutter: Gesture arena 1 ❙ Closing with 3 members. flutter: Gesture arena 1 ❙ Rejecting: LongPressGestureRecognizer#fec4e(debugOwner: _TextSelectionGestureDetectorState#1676e, state: possible) flutter: Gesture arena 1 ❙ Accepting: TapAndHorizontalDragGestureRecognizer#dc538(debugOwner: _TextSelectionGestureDetectorState#1676e) flutter: Gesture arena 1 ❙ Self-declared winner: TapAndHorizontalDragGestureRecognizer#dc538(debugOwner: _TextSelectionGestureDetectorState#1676e) ```https://user-images.githubusercontent.com/64651636/230674533-5a53f23b-211c-411d-b2d8-3831cc7db6af.mov
https://user-images.githubusercontent.com/64651636/230674441-dedd85df-1543-4de1-bec5-581c2bc411b6.mov