Conversation
…ick marks Port of flutter/flutter#188012. Tick marks and the thumb on discrete rounded tracks are painted in a coordinate space padded by half a track height on each end, but the gesture math used an unpadded formula, so lower-half tick taps could snap to the wrong (lower) division. Mirrors the padded geometry in _getValueFromGlobalPosition (Slider and RangeSlider) and in the drag-delta normalizer so tap and drag stay in the same coordinate space.
There was a problem hiding this comment.
Code Review
This pull request updates the coordinate calculations for discrete Slider and RangeSlider widgets with rounded tracks to ensure that tap and drag gestures align correctly with visual tick positions. The changes introduce padding adjustments in _getValueFromGlobalPosition and drag-delta calculations, and add corresponding regression tests. Review feedback suggests replacing null-assertions on slider theme track shapes with optional chaining to prevent potential runtime crashes, and handling potential division-by-zero cases when the track width is zero or negative.
| if (isDiscrete && _sliderTheme.rangeTrackShape!.isRounded) { | ||
| final double padding = _trackRect.height; | ||
| final double adjustedWidth = _trackRect.width - padding; | ||
| if (adjustedWidth <= 0.0) { | ||
| visualPosition = 0.5; | ||
| } else { | ||
| visualPosition = (localDx - _trackRect.left - padding / 2) / adjustedWidth; | ||
| } | ||
| } else { | ||
| visualPosition = (localDx - _trackRect.left) / _trackRect.width; | ||
| } |
There was a problem hiding this comment.
Using the null-assert operator (!) on _sliderTheme.rangeTrackShape can lead to a runtime crash if the range track shape is null in the theme. It is safer to use optional chaining (?.) with a fallback value to ensure robustness. Additionally, handling the case where _trackRect.width is <= 0.0 in the else branch prevents potential division-by-zero errors.
if (isDiscrete && (_sliderTheme.rangeTrackShape?.isRounded ?? false)) {
final double padding = _trackRect.height;
final double adjustedWidth = _trackRect.width - padding;
if (adjustedWidth <= 0.0) {
visualPosition = 0.5;
} else {
visualPosition = (localDx - _trackRect.left - padding / 2) / adjustedWidth;
}
} else {
visualPosition = _trackRect.width <= 0.0
? 0.5
: (localDx - _trackRect.left) / _trackRect.width;
}| double get _discreteRoundedTrackPadding => | ||
| (isDiscrete && _sliderTheme.trackShape!.isRounded) ? _trackRect.height : 0.0; |
There was a problem hiding this comment.
Using the null-assert operator (!) on _sliderTheme.trackShape can lead to a runtime crash if the track shape is null in the theme. It is safer to use optional chaining (?.) with a fallback value to ensure robustness.
double get _discreteRoundedTrackPadding =>
(isDiscrete && (_sliderTheme.trackShape?.isRounded ?? false)) ? _trackRect.height : 0.0;
QuncCccccc
left a comment
There was a problem hiding this comment.
Thanks for your contribution. Seems the comments from the original PRs haven't been addressed, so I just copied and pasted here:)
|
|
||
| await tester.pumpWidget( | ||
| MaterialApp( | ||
| theme: ThemeData(useMaterial3: true), |
There was a problem hiding this comment.
We can remove this line because useMaterial3 is true by default.
|
|
||
| await tester.pumpWidget( | ||
| MaterialApp( | ||
| theme: ThemeData(useMaterial3: false), |
There was a problem hiding this comment.
Seems this test is only checking M2. M3 might be more important to test since M2 has become a out of date style. We can remove this line to test the default value - M3.
|
|
||
| await tester.pumpWidget( | ||
| MaterialApp( | ||
| theme: ThemeData(useMaterial3: false), |
|
|
||
| await tester.pumpWidget( | ||
| MaterialApp( | ||
| theme: ThemeData(useMaterial3: false), |
Ports flutter/flutter#188012 to
material_uinow that the Material/Cupertino code freeze has lifted, per the instructions in flutter/flutter#188444.Original PR description:
Fixes flutter/flutter#184391
Tick marks and the thumb on discrete rounded tracks are painted in a padded coordinate space:
where
padding = trackHeight(4 px on M2'sRoundedRectSliderTrackShape, up to 16 px on M3'sGappedSliderTrackShape). But tap detection inverted a different, unpadded formula, so the snap midpoints in tap space diverged from the visual midpoints between tick marks. Lower-half ticks consistently landed in the wrong snap bucket.Fix:
_getValueFromGlobalPositionnow uses the padded inverse formula whenisDiscrete && trackShape.isRounded. The drag-delta normalizer in_handleDragUpdateis updated to match so a tap followed immediately by a drag is consistent.Applied to both
SliderandRangeSlider.Tests
Ported the five regression tests from the original PR to
slider_test.dart, covering M2/M3 LTR, RTL, tap-then-drag, and near-tick-boundary taps. All existingslider_test.dart(112) andrange_slider_test.dart(69) tests pass locally.Fixes flutter/flutter#184391
Closes flutter/flutter#188012 (superseded by this PR)