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.
|
/// A [RangeSlider] track that's a simple rectangle.
|
||||||
///
|
///
|
||||||
/// It paints a solid colored rectangle, vertically centered in the
|
/// It paints a solid colored rectangle, vertically centered in the
|
||||||
@ -1798,35 +1844,13 @@ class RoundedRectSliderTrackShape extends SliderTrackShape with BaseSliderTrackS
|
|||||||
/// the [RangeSlider]'s track.
|
/// the [RangeSlider]'s track.
|
||||||
/// * [RoundedRectRangeSliderTrackShape], for a similar track with rounded
|
/// * [RoundedRectRangeSliderTrackShape], for a similar track with rounded
|
||||||
/// edges.
|
/// edges.
|
||||||
class RectangularRangeSliderTrackShape extends RangeSliderTrackShape {
|
class RectangularRangeSliderTrackShape extends RangeSliderTrackShape with BaseRangeSliderTrackShape {
|
||||||
/// Create a slider track with rectangular outer edges.
|
/// Create a slider track with rectangular outer edges.
|
||||||
///
|
///
|
||||||
/// The middle track segment is the selected range and is active, and the two
|
/// The middle track segment is the selected range and is active, and the two
|
||||||
/// outer track segments are inactive.
|
/// outer track segments are inactive.
|
||||||
const RectangularRangeSliderTrackShape();
|
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
|
@override
|
||||||
void paint(
|
void paint(
|
||||||
PaintingContext context,
|
PaintingContext context,
|
||||||
@ -1913,36 +1937,13 @@ class RectangularRangeSliderTrackShape extends RangeSliderTrackShape {
|
|||||||
/// * [RangeSliderTrackShape], which can be used to create custom shapes for
|
/// * [RangeSliderTrackShape], which can be used to create custom shapes for
|
||||||
/// the [RangeSlider]'s track.
|
/// the [RangeSlider]'s track.
|
||||||
/// * [RectangularRangeSliderTrackShape], for a similar track with sharp edges.
|
/// * [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.
|
/// Create a slider track with rounded outer edges.
|
||||||
///
|
///
|
||||||
/// The middle track segment is the selected range and is active, and the two
|
/// The middle track segment is the selected range and is active, and the two
|
||||||
/// outer track segments are inactive.
|
/// outer track segments are inactive.
|
||||||
const RoundedRectRangeSliderTrackShape();
|
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
|
@override
|
||||||
void paint(
|
void paint(
|
||||||
PaintingContext context,
|
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
|
// Only the thumb, overlay, and tick mark have special shortcuts to provide
|
||||||
// no-op or empty shapes.
|
// no-op or empty shapes.
|
||||||
//
|
//
|
||||||
|
Loading…
x
Reference in New Issue
Block a user