Unverified Commit f733e3a4 authored by yim's avatar yim Committed by GitHub

Fix multiple calls to Slider's onChanged. (#143680)

Fixes #143524
parent ff9b1a5c
...@@ -612,6 +612,11 @@ class _SliderState extends State<Slider> with TickerProviderStateMixin { ...@@ -612,6 +612,11 @@ class _SliderState extends State<Slider> with TickerProviderStateMixin {
bool _dragging = false; bool _dragging = false;
// For discrete sliders, _handleChanged might receive the same value
// multiple times. To avoid calling widget.onChanged repeatedly, the
// value from _handleChanged is temporarily saved here.
double? _currentChangedValue;
FocusNode? _focusNode; FocusNode? _focusNode;
FocusNode get focusNode => widget.focusNode ?? _focusNode!; FocusNode get focusNode => widget.focusNode ?? _focusNode!;
...@@ -664,8 +669,11 @@ class _SliderState extends State<Slider> with TickerProviderStateMixin { ...@@ -664,8 +669,11 @@ class _SliderState extends State<Slider> with TickerProviderStateMixin {
void _handleChanged(double value) { void _handleChanged(double value) {
assert(widget.onChanged != null); assert(widget.onChanged != null);
final double lerpValue = _lerp(value); final double lerpValue = _lerp(value);
if (lerpValue != widget.value) { if (_currentChangedValue != lerpValue) {
widget.onChanged!(lerpValue); _currentChangedValue = lerpValue;
if (_currentChangedValue != widget.value) {
widget.onChanged!(_currentChangedValue!);
}
} }
} }
...@@ -676,6 +684,7 @@ class _SliderState extends State<Slider> with TickerProviderStateMixin { ...@@ -676,6 +684,7 @@ class _SliderState extends State<Slider> with TickerProviderStateMixin {
void _handleDragEnd(double value) { void _handleDragEnd(double value) {
_dragging = false; _dragging = false;
_currentChangedValue = null;
widget.onChangeEnd?.call(_lerp(value)); widget.onChangeEnd?.call(_lerp(value));
} }
......
...@@ -4253,4 +4253,32 @@ void main() { ...@@ -4253,4 +4253,32 @@ void main() {
); );
}); });
}); });
// This is a regression test for https://github.com/flutter/flutter/issues/143524.
testWidgets('Discrete Slider.onChanged is called only once', (WidgetTester tester) async {
int onChangeCallbackCount = 0;
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: Center(
child: Slider(
max: 5,
divisions: 5,
value: 0,
onChanged: (double newValue) {
onChangeCallbackCount++;
},
),
),
),
),
);
final TestGesture gesture = await tester.startGesture(tester.getTopLeft(find.byType(Slider)));
await tester.pump(kLongPressTimeout);
await gesture.moveBy(const Offset(160.0, 0.0));
await gesture.moveBy(const Offset(1.0, 0.0));
await gesture.moveBy(const Offset(1.0, 0.0));
expect(onChangeCallbackCount, 1);
});
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment