diff --git a/packages/flutter/lib/src/material/slider.dart b/packages/flutter/lib/src/material/slider.dart index be5a5893e3a..f0d16818e3a 100644 --- a/packages/flutter/lib/src/material/slider.dart +++ b/packages/flutter/lib/src/material/slider.dart @@ -881,6 +881,7 @@ class _SliderRenderObjectWidget extends LeafRenderObjectWidget { platform: Theme.of(context).platform, hasFocus: hasFocus, hovering: hovering, + gestureSettings: MediaQuery.of(context).gestureSettings, ); } @@ -902,7 +903,8 @@ class _SliderRenderObjectWidget extends LeafRenderObjectWidget { ..semanticFormatterCallback = semanticFormatterCallback ..platform = Theme.of(context).platform ..hasFocus = hasFocus - ..hovering = hovering; + ..hovering = hovering + ..gestureSettings = MediaQuery.of(context).gestureSettings; // Ticker provider cannot change since there's a 1:1 relationship between // the _SliderRenderObjectWidget object and the _SliderState object. } @@ -925,6 +927,7 @@ class _RenderSlider extends RenderBox with RelayoutWhenSystemFontsChangeMixin { required TextDirection textDirection, required bool hasFocus, required bool hovering, + required DeviceGestureSettings gestureSettings, }) : assert(value != null && value >= 0.0 && value <= 1.0), assert(state != null), assert(textDirection != null), @@ -948,11 +951,13 @@ class _RenderSlider extends RenderBox with RelayoutWhenSystemFontsChangeMixin { ..onStart = _handleDragStart ..onUpdate = _handleDragUpdate ..onEnd = _handleDragEnd - ..onCancel = _endInteraction; + ..onCancel = _endInteraction + ..gestureSettings = gestureSettings; _tap = TapGestureRecognizer() ..team = team ..onTapDown = _handleTapDown - ..onTapUp = _handleTapUp; + ..onTapUp = _handleTapUp + ..gestureSettings = gestureSettings; _overlayAnimation = CurvedAnimation( parent: _state.overlayController, curve: Curves.fastOutSlowIn, @@ -1037,6 +1042,12 @@ class _RenderSlider extends RenderBox with RelayoutWhenSystemFontsChangeMixin { markNeedsSemanticsUpdate(); } + DeviceGestureSettings? get gestureSettings => _drag.gestureSettings; + set gestureSettings(DeviceGestureSettings? gestureSettings) { + _drag.gestureSettings = gestureSettings; + _tap.gestureSettings = gestureSettings; + } + TargetPlatform _platform; TargetPlatform get platform => _platform; set platform(TargetPlatform value) { diff --git a/packages/flutter/test/material/slider_test.dart b/packages/flutter/test/material/slider_test.dart index 8e935b7b01d..084ff369cbc 100644 --- a/packages/flutter/test/material/slider_test.dart +++ b/packages/flutter/test/material/slider_test.dart @@ -6,6 +6,7 @@ import 'dart:ui'; import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; +import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/scheduler.dart'; @@ -2998,4 +2999,111 @@ void main() { paints..rrect()..rrect()..rrect()..rrect()..rrect()..rrect(color: color), ); }); + + // Regression test for https://github.com/flutter/flutter/issues/103566 + testWidgets('Drag gesture uses provided gesture settings', (WidgetTester tester) async { + double value = 0.5; + bool dragStarted = false; + final Key sliderKey = UniqueKey(); + + await tester.pumpWidget( + MaterialApp( + home: Directionality( + textDirection: TextDirection.ltr, + child: StatefulBuilder( + builder: (BuildContext context, StateSetter setState) { + return Material( + child: Center( + child: GestureDetector( + behavior: HitTestBehavior.deferToChild, + onHorizontalDragStart: (DragStartDetails details) { + dragStarted = true; + }, + child: MediaQuery( + data: MediaQuery.of(context).copyWith(gestureSettings: const DeviceGestureSettings(touchSlop: 20)), + child: Slider( + value: value, + key: sliderKey, + onChanged: (double newValue) { + setState(() { + value = newValue; + }); + }, + ), + ), + ), + ), + ); + }, + ), + ), + ), + ); + + TestGesture drag = await tester.startGesture(tester.getCenter(find.byKey(sliderKey))); + await tester.pump(kPressTimeout); + + // Less than configured touch slop, more than default touch slop + await drag.moveBy(const Offset(19.0, 0)); + await tester.pump(); + + expect(value, 0.5); + expect(dragStarted, true); + + dragStarted = false; + + await drag.up(); + await tester.pumpAndSettle(); + + drag = await tester.startGesture(tester.getCenter(find.byKey(sliderKey))); + await tester.pump(kPressTimeout); + + bool sliderEnd = false; + + await tester.pumpWidget( + MaterialApp( + home: Directionality( + textDirection: TextDirection.ltr, + child: StatefulBuilder( + builder: (BuildContext context, StateSetter setState) { + return Material( + child: Center( + child: GestureDetector( + behavior: HitTestBehavior.deferToChild, + onHorizontalDragStart: (DragStartDetails details) { + dragStarted = true; + }, + child: MediaQuery( + data: MediaQuery.of(context).copyWith(gestureSettings: const DeviceGestureSettings(touchSlop: 10)), + child: Slider( + value: value, + key: sliderKey, + onChanged: (double newValue) { + setState(() { + value = newValue; + }); + }, + onChangeEnd: (double endValue) { + sliderEnd = true; + }, + ), + ), + ), + ), + ); + }, + ), + ), + ), + ); + + // More than touch slop. + await drag.moveBy(const Offset(12.0, 0)); + + await drag.up(); + await tester.pumpAndSettle(); + + expect(sliderEnd, true); + expect(dragStarted, false); + }); }