Repository navigation
Slider notifies "onChangeEnd" twice when it is over a InkWell/GestureDetector #28115
Description
Activity
- changed the title
[-]Slider notifies twitch "onChangeEnd" when over a InkWell/GestureDetector[/-][+]Slider notifies twice "onChangeEnd" when over a InkWell/GestureDetector[/+]on Feb 18, 2019 - changed the title
[-]Slider notifies twice "onChangeEnd" when over a InkWell/GestureDetector[/-][+]Slider notifies "onChangeEnd" twice when it is over a InkWell/GestureDetector[/+]on Feb 18, 2019 To investigate we would need a minimal runnable reproduction
as a single file so that we can just copy your code intolib/main.dartof a new project and run to reproduce.- addedwaiting for responseThe Flutter team cannot make further progress on this issue until the original reporter respondsThe Flutter team cannot make further progress on this issue until the original reporter responds
on Feb 19, 2019 To investigate we would need a minimal runnable reproduction
as a single file so that we can just copy your code intolib/main.dartof a new project and run to reproduce.Zoechi the one the post is exactly that. Actually this is a Scaffold. Just embed it into any MaterialApp will run properly.
To be runnable it should include
main() {...}.
The point is that we shouldn't need to make any assumptions. Just copy-paste and run.
Otherwise there is always room for different behavior.- addedframeworkflutter/packages/flutter repository. See also f: labels.flutter/packages/flutter repository. See also f: labels.
on Feb 19, 2019 Understood! I've updated the code above with the requirements.
Thanks!
I wasn't able to reproduce though.
[✓] Flutter (Channel master, v1.2.2-pre.21, on Mac OS X 10.14.3 18D42, locale en-AT) [✓] Connected device (1 available) • Android SDK built for x86 • emulator-5554 • android-x86 • Android 9 (API 28) (emulator)Can you please try with
master(ordev) channel?flutter channel master flutter doctorI just switched to 1.2.2-pre.21 and seems the problem is gone. You may close the issue if you want :)
Also, this issue seems related to this same problem: #18561Edit: Actually it is not gone, check comment below.
Reacted by Günter Zöchbauer- removedwaiting for responseThe Flutter team cannot make further progress on this issue until the original reporter respondsThe Flutter team cannot make further progress on this issue until the original reporter responds
on Feb 19, 2019 @zoechi Actually I've posted a wrong code snippet on this issue and tested it on my machine wrongly too... My bad!
The issue still persist on v1.2.2-pre.21.
I've updated the code snippet above so you can check for yourself.41 remaining items
- addedfound in release: 1.22Found to occur in 1.22Found to occur in 1.22found in release: 1.26Found to occur in 1.26Found to occur in 1.26
on Jan 20, 2021 Same issue. Running Flutter stable 1.22.5
This problem doesn't arise in
CupertinoSlider!
CupertinoSliderdiffers fromSliderin that it doesn't define aTapGestureRecognizer:Slider:
_drag = HorizontalDragGestureRecognizer() ..team = team ..onStart = _handleDragStart ..onUpdate = _handleDragUpdate ..onEnd = _handleDragEnd ..onCancel = _endInteraction; _tap = TapGestureRecognizer() ..team = team ..onTapDown = _handleTapDown ..onTapUp = _handleTapUp ..onTapCancel = _endInteraction;
CupertinoSlider:
_drag = HorizontalDragGestureRecognizer() ..onStart = _handleDragStart ..onUpdate = _handleDragUpdate ..onEnd = _handleDragEnd;
So the problem is probably related to
Sliderreacting to the initial "tap" when beginning to drag the slider thumb. In that moment,onChangeEndis called the first time. When the dragging really ends, it is called the second time.Finding a workaround
I wrapped my
Sliderwith aGestureDetectorand started checking which events are triggered:GestureDetector( onHorizontalDragCancel: () => print("GESTURE DETECTOR onHorizontalDragCancel"), child: Slider( ... value: ..., onChanged: ..., onChangeStart: (value) { print("SLIDER onChangeStart"); }, onChangeEnd: (value) { print("SLIDER onChangeEnd"); }, ), )
Then, I identified the following patterns:
- When simply clicking somewhere on the slider:
flutter: GESTURE DETECTOR onHorizontalDragCancel flutter: SLIDER onChangeStart flutter: SLIDER onChangeEnd- When dragging the slider thumb somewhere:
flutter: SLIDER onChangeStart flutter: GESTURE DETECTOR onHorizontalDragCancel flutter: SLIDER onChangeEnd flutter: SLIDER onChangeStart flutter: SLIDER onChangeEndI identified that the
onHorizontalDragCancelthat is triggered in 2. after the firstonChangeStartcan be helpful.
So I came up with the following workaround.My workaround
I use a property
_cancelledwithin myStatein order to check whetheronHorizontalDragCancelhas been triggered betweenonChangeStartandonChangeEnd. If yes, then the call toonChangeEndis ignored!bool _cancelled = false; ... GestureDetector( onHorizontalDragCancel: () => _cancelled = true, child: Slider( ... value: ..., onChanged: ..., onChangeStart: (value) => _cancelled = false, onChangeEnd: (value) { if (_cancelled) return; // do onChangeEnd stuff }, ), )
Now, the slider's
onChangeEndis called only once! Enjoy!Reacted by Łukasz NiedziałekReacted by KurodaSayama, aleron08, Tiger, Harsh Bhikadia, Mikhail Chernousov, Sauceee, Guilherme, Alex Adrianov, Max Luchterhand and Ujjwal Maity@WieFel Thanks for the workaround!!
I am facing this in v2 too.
Reacted by Felix@WieFel, Thanks for your workaround! You're breathtaking!
Reacted by FelixUnfortunately for me non-of above solutions worked for me, although they worked as great examples for my work around:
bool _cancelBugEvent = true; Slider( min: 0.0, max: 1.0, onChanged: (value) async { }, onChangeStart: (value) async { }, onChangeEnd: (value) async { ///FIXME: https://github.com/flutter/flutter/issues/28115 if (_cancelBugEvent) { _cancelBugEvent = false; } else if (!_cancelBugEvent) { _cancelBugEvent = true; //execute code when drag released } };Is there a release plan we can track? Thanks in advance!
I'm using
Slider.adaptiveand this problem only occurs on Android (material slider) devices. The cupertino version of the adaptive slider works fine.This makes it even harder because none of the fixes mentioned above work without breaking the other platforms widget.
flutter doctor
[✓] Flutter (Channel stable, 2.0.2, on macOS 11.1 20C69 darwin-x64, locale en-GB) • Flutter version 2.0.2 at /Users/user/development/flutter • Framework revision 8962f6dc68 (13 days ago), 2021-03-11 13:22:20 -0800 • Engine revision 5d8bf811b3 • Dart version 2.12.1 [✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3) • Android SDK at /Users/user/Library/Android/sdk • Platform android-30, build-tools 30.0.3 • Java binary at: /Users/user/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/201.7199119/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495) • All Android licenses accepted. [✓] Xcode - develop for iOS and macOS • Xcode at /Applications/Xcode.app/Contents/Developer • Xcode 12.4, Build version 12D4e • CocoaPods version 1.10.1 [✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome [✓] Android Studio (version 4.1) • Android Studio at /Users/user/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/201.7199119/Android Studio.app/Contents • Flutter plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/9212-flutter • Dart plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/6351-dart • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495)@WieFel This workaround is not so reliable.
I think a correct flow is onChangeStart -> onChanged -> onChangeEnd, except for onChanged the other methods can only appear once.Most of the current cases are fine, we can also set a
_completeflag to control the number of appearances of onChangeStart.onHorizontalDragCancel: () { _cancelled = true; print('onHorizontalDragCancel'); }onChangeStart: (double value) { if(_complete){ print('onChangeStart'); } _complete = false; _cancelled = false; }, onChanged: () => print('onChanged');, onChangeEnd: (double value) { if(_cancelled) return; _complete = true; print('onChangeEnd') }If you drop the area outside the thumb, then pause for a moment and continue sliding, the print log looks like this
onChangeStart: 0.48814937736414643 onChanged: 0.29379905024661296 onChangeEnd: 0.29379905024661296 onHorizontalDragCancel onChangeStart: 0.29379905024661296 onChanged: 0.2353359415561338 onChanged: 0.23375586014759692 onChanged: 0.23217577873906003 onChangeEnd: 0.23059569733052315dh_slider uses a delay as a workaround, it's not a great way to do it, but it's safer.
Reacted by FelixHello, I am experiencing the same problem with Slider in version 2.0.5 of Flutter. The function is triggered twice.
I have the same problem :(( any solution for this?
- addedr: fixedIssue is closed as already fixed in a newer versionIssue is closed as already fixed in a newer version
on May 21, 2021 I am also having a problem with the slider. I just added a fix on the update to check the current value and the old value are not the same, then I will send the update to the cloud.
But now I am facing another problem also related to the same issue. I realised the problem is happening because I am not tapping on the center of the slider. If I tap exactly on the same, then the onchangedEnd event fires with the same value otherwise I am get a different value. One at the start and another event at the end.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 -vand a minimal reproduction of the issue.- locked as resolved and limited conversation to collaborators
on Jul 30, 2021
When embedding a Slider inside a InkWell, the Slider fires twice "onChangeEnd" if you start dragging it.
Check this snippet:
If you just tap somewhere in the slider's "line" verything works fine. But if you drag it, it will fire twict the "onChanceEnd" method.
I also realized the if you drag too fast, it will fires only once. But users don't use the sliders like that. I believe this has something related to the InkWell/GestureDetector that is behind it....