mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Fix discrete Slider and RangeSlider to enforce thumb height padding when the track shape is non-rounded (#164703)
Fixes [Discrete `Slider` and `RangeSlider` applies thumb padding when using custom Slider shapes](https://github.com/flutter/flutter/issues/161805) ### Code Sample <details> <summary>expand to view the code sample</summary> ```dart import 'package:flutter/material.dart'; void main() => runApp(const RangeSliderExampleApp()); class RangeSliderExampleApp extends StatelessWidget { const RangeSliderExampleApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, theme: ThemeData( sliderTheme: const SliderThemeData( trackHeight: 32, trackShape: RectangularSliderTrackShape(), rangeTrackShape: RectangularRangeSliderTrackShape(), thumbColor: Colors.amber, ), ), home: Scaffold( body: Column( spacing: 20.0, mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Slider( value: 100, max: 100, divisions: 100, onChanged: (double value) {}, ), RangeSlider( values: const RangeValues(0, 100), max: 100, divisions: 100, onChanged: (RangeValues values) {}, ), ], ), ), ); } } ``` </details> ### Before <img width="929" alt="Screenshot 2025-03-06 at 13 33 17" src="https://github.com/user-attachments/assets/a089674f-4931-4808-9663-1cd540bf7b11" /> ### After <img width="929" alt="Screenshot 2025-03-06 at 13 33 28" src="https://github.com/user-attachments/assets/77fe5708-f2e4-4734-92c2-46e4d8338d0e" /> ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [ ] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [ ] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
This commit is contained in:
parent
f88cde1e01
commit
b6e964bd0c
@ -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,
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@ -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),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user