fix RangeSlider, with no overlayShape shifts to the left (#125483)
This commit is contained in:
parent
55c988fb45
commit
f87d208742
@ -1771,6 +1771,52 @@ class RoundedRectSliderTrackShape extends SliderTrackShape with BaseSliderTrackS
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Base range slider track shape that provides an implementation of [getPreferredRect] for
|
||||
/// default sizing.
|
||||
///
|
||||
/// The height is set from [SliderThemeData.trackHeight] and the width of the
|
||||
/// parent box less the larger of the widths of [SliderThemeData.rangeThumbShape] and
|
||||
/// [SliderThemeData.overlayShape].
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [RectangularRangeSliderTrackShape], which is a track shape with sharp
|
||||
/// rectangular edges
|
||||
mixin BaseRangeSliderTrackShape {
|
||||
/// Returns a rect that represents the track bounds that fits within the
|
||||
/// [Slider].
|
||||
///
|
||||
/// The width is the width of the [RangeSlider], but padded by the max
|
||||
/// of the overlay and thumb radius. The height is defined by the [SliderThemeData.trackHeight].
|
||||
///
|
||||
/// The [Rect] is centered both horizontally and vertically within the slider
|
||||
/// bounds.
|
||||
Rect getPreferredRect({
|
||||
required RenderBox parentBox,
|
||||
Offset offset = Offset.zero,
|
||||
required SliderThemeData sliderTheme,
|
||||
bool isEnabled = false,
|
||||
bool isDiscrete = false,
|
||||
}) {
|
||||
assert(sliderTheme.rangeThumbShape != null);
|
||||
assert(sliderTheme.overlayShape != null);
|
||||
assert(sliderTheme.trackHeight != null);
|
||||
final double thumbWidth = sliderTheme.rangeThumbShape!.getPreferredSize(isEnabled, isDiscrete).width;
|
||||
final double overlayWidth = sliderTheme.overlayShape!.getPreferredSize(isEnabled, isDiscrete).width;
|
||||
final double trackHeight = sliderTheme.trackHeight!;
|
||||
assert(overlayWidth >= 0);
|
||||
assert(trackHeight >= 0);
|
||||
|
||||
final double trackLeft = offset.dx + math.max(overlayWidth / 2, thumbWidth / 2);
|
||||
final double trackTop = offset.dy + (parentBox.size.height - trackHeight) / 2;
|
||||
final double trackRight = trackLeft + parentBox.size.width - math.max(thumbWidth, overlayWidth);
|
||||
final double trackBottom = trackTop + trackHeight;
|
||||
// If the parentBox'size less than slider's size the trackRight will be less than trackLeft, so switch them.
|
||||
return Rect.fromLTRB(math.min(trackLeft, trackRight), trackTop, math.max(trackLeft, trackRight), trackBottom);
|
||||
}
|
||||
}
|
||||
|
||||
/// A [RangeSlider] track that's a simple rectangle.
|
||||
///
|
||||
/// It paints a solid colored rectangle, vertically centered in the
|
||||
@ -1798,35 +1844,13 @@ class RoundedRectSliderTrackShape extends SliderTrackShape with BaseSliderTrackS
|
||||
/// the [RangeSlider]'s track.
|
||||
/// * [RoundedRectRangeSliderTrackShape], for a similar track with rounded
|
||||
/// edges.
|
||||
class RectangularRangeSliderTrackShape extends RangeSliderTrackShape {
|
||||
class RectangularRangeSliderTrackShape extends RangeSliderTrackShape with BaseRangeSliderTrackShape {
|
||||
/// Create a slider track with rectangular outer edges.
|
||||
///
|
||||
/// The middle track segment is the selected range and is active, and the two
|
||||
/// outer track segments are inactive.
|
||||
const RectangularRangeSliderTrackShape();
|
||||
|
||||
@override
|
||||
Rect getPreferredRect({
|
||||
required RenderBox parentBox,
|
||||
Offset offset = Offset.zero,
|
||||
required SliderThemeData sliderTheme,
|
||||
bool isEnabled = false,
|
||||
bool isDiscrete = false,
|
||||
}) {
|
||||
assert(sliderTheme.overlayShape != null);
|
||||
final double overlayWidth = sliderTheme.overlayShape!.getPreferredSize(isEnabled, isDiscrete).width;
|
||||
final double trackHeight = sliderTheme.trackHeight!;
|
||||
assert(overlayWidth >= 0);
|
||||
assert(trackHeight >= 0);
|
||||
|
||||
final double trackLeft = offset.dx + overlayWidth / 2;
|
||||
final double trackTop = offset.dy + (parentBox.size.height - trackHeight) / 2;
|
||||
final double trackRight = trackLeft + parentBox.size.width - overlayWidth;
|
||||
final double trackBottom = trackTop + trackHeight;
|
||||
// If the parentBox'size less than slider's size the trackRight will be less than trackLeft, so switch them.
|
||||
return Rect.fromLTRB(math.min(trackLeft, trackRight), trackTop, math.max(trackLeft, trackRight), trackBottom);
|
||||
}
|
||||
|
||||
@override
|
||||
void paint(
|
||||
PaintingContext context,
|
||||
@ -1913,36 +1937,13 @@ class RectangularRangeSliderTrackShape extends RangeSliderTrackShape {
|
||||
/// * [RangeSliderTrackShape], which can be used to create custom shapes for
|
||||
/// the [RangeSlider]'s track.
|
||||
/// * [RectangularRangeSliderTrackShape], for a similar track with sharp edges.
|
||||
class RoundedRectRangeSliderTrackShape extends RangeSliderTrackShape {
|
||||
class RoundedRectRangeSliderTrackShape extends RangeSliderTrackShape with BaseRangeSliderTrackShape {
|
||||
/// Create a slider track with rounded outer edges.
|
||||
///
|
||||
/// The middle track segment is the selected range and is active, and the two
|
||||
/// outer track segments are inactive.
|
||||
const RoundedRectRangeSliderTrackShape();
|
||||
|
||||
@override
|
||||
Rect getPreferredRect({
|
||||
required RenderBox parentBox,
|
||||
Offset offset = Offset.zero,
|
||||
required SliderThemeData sliderTheme,
|
||||
bool isEnabled = false,
|
||||
bool isDiscrete = false,
|
||||
}) {
|
||||
assert(sliderTheme.overlayShape != null);
|
||||
assert(sliderTheme.trackHeight != null);
|
||||
final double overlayWidth = sliderTheme.overlayShape!.getPreferredSize(isEnabled, isDiscrete).width;
|
||||
final double trackHeight = sliderTheme.trackHeight!;
|
||||
assert(overlayWidth >= 0);
|
||||
assert(trackHeight >= 0);
|
||||
|
||||
final double trackLeft = offset.dx + overlayWidth / 2;
|
||||
final double trackTop = offset.dy + (parentBox.size.height - trackHeight) / 2;
|
||||
final double trackRight = trackLeft + parentBox.size.width - overlayWidth;
|
||||
final double trackBottom = trackTop + trackHeight;
|
||||
// If the parentBox'size less than slider's size the trackRight will be less than trackLeft, so switch them.
|
||||
return Rect.fromLTRB(math.min(trackLeft, trackRight), trackTop, math.max(trackLeft, trackRight), trackBottom);
|
||||
}
|
||||
|
||||
@override
|
||||
void paint(
|
||||
PaintingContext context,
|
||||
|
@ -1430,6 +1430,51 @@ void main() {
|
||||
);
|
||||
});
|
||||
|
||||
// Regression test for https://github.com/flutter/flutter/issues/125467
|
||||
testWidgets('The RangeSlider track layout correctly when the overlay size is smaller than the thumb size', (WidgetTester tester) async {
|
||||
final SliderThemeData sliderTheme = ThemeData().sliderTheme.copyWith(
|
||||
overlayShape: SliderComponentShape.noOverlay,
|
||||
);
|
||||
|
||||
await tester.pumpWidget(_buildRangeApp(sliderTheme, values: const RangeValues(0.0, 1.0)));
|
||||
|
||||
final MaterialInkController material = Material.of(
|
||||
tester.element(find.byType(RangeSlider)),
|
||||
);
|
||||
|
||||
// The track rectangle begins at 10 pixels from the left of the screen and ends 10 pixels from the right
|
||||
// (790 pixels from the left). The main check here it that the track itself should be centered on
|
||||
// the 800 pixel-wide screen.
|
||||
expect(
|
||||
material,
|
||||
paints
|
||||
// active track RRect. Starts 10 pixels from left of screen.
|
||||
..rrect(rrect: RRect.fromLTRBAndCorners(
|
||||
10.0,
|
||||
298.0,
|
||||
10.0,
|
||||
302.0,
|
||||
topLeft: const Radius.circular(2.0),
|
||||
bottomLeft: const Radius.circular(2.0),
|
||||
))
|
||||
// active track RRect Start 10 pixels from left screen.
|
||||
..rect(rect:const Rect.fromLTRB(10.0, 297.0, 790.0, 303.0),)
|
||||
// inactive track RRect. Ends 10 pixels from right of screen.
|
||||
..rrect(rrect: RRect.fromLTRBAndCorners(
|
||||
790.0,
|
||||
298.0,
|
||||
790.0,
|
||||
302.0,
|
||||
topRight: const Radius.circular(2.0),
|
||||
bottomRight: const Radius.circular(2.0),
|
||||
))
|
||||
// The thumb Left.
|
||||
..circle(x: 10.0, y: 300.0, radius: 10.0)
|
||||
// The thumb Right.
|
||||
..circle(x: 790.0, y: 300.0, radius: 10.0),
|
||||
);
|
||||
});
|
||||
|
||||
// Only the thumb, overlay, and tick mark have special shortcuts to provide
|
||||
// no-op or empty shapes.
|
||||
//
|
||||
|
Loading…
x
Reference in New Issue
Block a user