diff --git a/packages/flutter/lib/src/material/range_slider.dart b/packages/flutter/lib/src/material/range_slider.dart index 5fd0a065f5f..d21cfefb532 100644 --- a/packages/flutter/lib/src/material/range_slider.dart +++ b/packages/flutter/lib/src/material/range_slider.dart @@ -1492,8 +1492,7 @@ class _RenderRangeSlider extends RenderBox with RelayoutWhenSystemFontsChangeMix sliderTheme: _sliderTheme, isDiscrete: isDiscrete, ); - final double padding = - isDiscrete || _sliderTheme.rangeTrackShape!.isRounded ? trackRect.height : 0.0; + final double padding = _sliderTheme.rangeTrackShape!.isRounded ? trackRect.height : 0.0; final double thumbYOffset = trackRect.center.dy; final double startThumbPosition = isDiscrete @@ -1586,8 +1585,8 @@ class _RenderRangeSlider extends RenderBox with RelayoutWhenSystemFontsChangeMix _sliderTheme.rangeTickMarkShape! .getPreferredSize(isEnabled: isEnabled, sliderTheme: _sliderTheme) .width; - final double padding = trackRect.height; - final double adjustedTrackWidth = trackRect.width - padding; + final double discreteTrackPadding = trackRect.height; + final double adjustedTrackWidth = trackRect.width - discreteTrackPadding; // If the tick marks would be too dense, don't bother painting them. if (adjustedTrackWidth / divisions! >= 3.0 * tickMarkWidth) { final double dy = trackRect.center.dy; @@ -1595,7 +1594,7 @@ class _RenderRangeSlider extends RenderBox with RelayoutWhenSystemFontsChangeMix final double value = i / divisions!; // The ticks are mapped to be within the track, so the tick mark width // must be subtracted from the track width. - final double dx = trackRect.left + value * adjustedTrackWidth + padding / 2; + final double dx = trackRect.left + value * adjustedTrackWidth + discreteTrackPadding / 2; final Offset tickMarkOffset = Offset(dx, dy); _sliderTheme.rangeTickMarkShape!.paint( context, diff --git a/packages/flutter/lib/src/material/slider.dart b/packages/flutter/lib/src/material/slider.dart index 45e06e5c5da..e42b39bafb6 100644 --- a/packages/flutter/lib/src/material/slider.dart +++ b/packages/flutter/lib/src/material/slider.dart @@ -1740,8 +1740,7 @@ class _RenderSlider extends RenderBox with RelayoutWhenSystemFontsChangeMixin { sliderTheme: _sliderTheme, isDiscrete: isDiscrete, ); - final double padding = - isDiscrete || _sliderTheme.trackShape!.isRounded ? trackRect.height : 0.0; + final double padding = _sliderTheme.trackShape!.isRounded ? trackRect.height : 0.0; final double thumbPosition = isDiscrete ? trackRect.left + visualPosition * (trackRect.width - padding) + padding / 2 @@ -1822,7 +1821,8 @@ class _RenderSlider extends RenderBox with RelayoutWhenSystemFontsChangeMixin { _sliderTheme.tickMarkShape! .getPreferredSize(isEnabled: isInteractive, sliderTheme: _sliderTheme) .width; - final double adjustedTrackWidth = trackRect.width - padding; + final double discreteTrackPadding = trackRect.height; + final double adjustedTrackWidth = trackRect.width - discreteTrackPadding; // If the tick marks would be too dense, don't bother painting them. if (adjustedTrackWidth / divisions! >= 3.0 * tickMarkWidth) { final double dy = trackRect.center.dy; @@ -1830,7 +1830,7 @@ class _RenderSlider extends RenderBox with RelayoutWhenSystemFontsChangeMixin { final double value = i / divisions!; // The ticks are mapped to be within the track, so the tick mark width // must be subtracted from the track width. - final double dx = trackRect.left + value * adjustedTrackWidth + padding / 2; + final double dx = trackRect.left + value * adjustedTrackWidth + discreteTrackPadding / 2; final Offset tickMarkOffset = Offset(dx, dy); _sliderTheme.tickMarkShape!.paint( context, diff --git a/packages/flutter/test/material/range_slider_test.dart b/packages/flutter/test/material/range_slider_test.dart index cc76c0d5e8a..9c9f5a5a64f 100644 --- a/packages/flutter/test/material/range_slider_test.dart +++ b/packages/flutter/test/material/range_slider_test.dart @@ -3093,4 +3093,47 @@ void main() { ..rrect(rrect: RRect.fromLTRBR(8.0, 7.0, 792.0, 13.0, const Radius.circular(2.0))), ); }); + + // Regression test for hhttps://github.com/flutter/flutter/issues/161805 + testWidgets('Discrete RangeSlider does not apply thumb padding in a non-rounded track shape', ( + WidgetTester tester, + ) async { + // The default track left and right padding. + const double sliderPadding = 24.0; + final ThemeData theme = ThemeData( + sliderTheme: const SliderThemeData( + // Thumb padding is applied based on the track height. + trackHeight: 100, + rangeTrackShape: RectangularRangeSliderTrackShape(), + ), + ); + + await tester.pumpWidget( + MaterialApp( + theme: theme, + home: Material( + child: SizedBox( + width: 300, + child: RangeSlider( + values: const RangeValues(0, 100), + max: 100, + divisions: 100, + onChanged: (RangeValues value) {}, + ), + ), + ), + ), + ); + + final MaterialInkController material = Material.of(tester.element(find.byType(RangeSlider))); + + expect( + material, + paints + // Start thumb. + ..circle(x: sliderPadding, y: 300.0, color: theme.colorScheme.primary) + // End thumb. + ..circle(x: 800.0 - sliderPadding, y: 300.0, color: theme.colorScheme.primary), + ); + }); } diff --git a/packages/flutter/test/material/slider_test.dart b/packages/flutter/test/material/slider_test.dart index 5da7f13a218..7b4d4240b20 100644 --- a/packages/flutter/test/material/slider_test.dart +++ b/packages/flutter/test/material/slider_test.dart @@ -5328,4 +5328,46 @@ void main() { await tester.pumpAndSettle(); expect(log.last, const Offset(400.0, 300.0)); }); + + // Regression test for hhttps://github.com/flutter/flutter/issues/161805 + testWidgets('Discrete Slider does not apply thumb padding in a non-rounded track shape', ( + WidgetTester tester, + ) async { + // The default track left and right padding. + const double sliderPadding = 24.0; + final ThemeData theme = ThemeData( + sliderTheme: const SliderThemeData( + // Thumb padding is applied based on the track height. + trackHeight: 100, + trackShape: RectangularSliderTrackShape(), + ), + ); + + Widget buildSlider({required double value}) { + return MaterialApp( + theme: theme, + home: Material( + child: SizedBox( + width: 300, + child: Slider(value: value, max: 100, divisions: 100, onChanged: (double value) {}), + ), + ), + ); + } + + await tester.pumpWidget(buildSlider(value: 0)); + + MaterialInkController material = Material.of(tester.element(find.byType(Slider))); + + expect(material, paints..circle(x: sliderPadding, y: 300.0, color: theme.colorScheme.primary)); + + await tester.pumpWidget(buildSlider(value: 100)); + await tester.pumpAndSettle(); + + material = Material.of(tester.element(find.byType(Slider))); + expect( + material, + paints..circle(x: 800.0 - sliderPadding, y: 300.0, color: theme.colorScheme.primary), + ); + }); }