Fix RangeSlider
semantics node size (#114999)
* Fix `RangeSlider` semantics node size and add RTL semantics test * Add TODO comments
This commit is contained in:
parent
09a4f23467
commit
1f891a0f33
@ -840,6 +840,8 @@ class _RenderRangeSlider extends RenderBox with RelayoutWhenSystemFontsChangeMix
|
||||
late TapGestureRecognizer _tap;
|
||||
bool _active = false;
|
||||
late RangeValues _newValues;
|
||||
late Offset _startThumbCenter;
|
||||
late Offset _endThumbCenter;
|
||||
|
||||
bool get isEnabled => onChanged != null;
|
||||
|
||||
@ -1303,8 +1305,8 @@ class _RenderRangeSlider extends RenderBox with RelayoutWhenSystemFontsChangeMix
|
||||
sliderTheme: _sliderTheme,
|
||||
isDiscrete: isDiscrete,
|
||||
);
|
||||
final Offset startThumbCenter = Offset(trackRect.left + startVisualPosition * trackRect.width, trackRect.center.dy);
|
||||
final Offset endThumbCenter = Offset(trackRect.left + endVisualPosition * trackRect.width, trackRect.center.dy);
|
||||
_startThumbCenter = Offset(trackRect.left + startVisualPosition * trackRect.width, trackRect.center.dy);
|
||||
_endThumbCenter = Offset(trackRect.left + endVisualPosition * trackRect.width, trackRect.center.dy);
|
||||
|
||||
_sliderTheme.rangeTrackShape!.paint(
|
||||
context,
|
||||
@ -1313,8 +1315,8 @@ class _RenderRangeSlider extends RenderBox with RelayoutWhenSystemFontsChangeMix
|
||||
sliderTheme: _sliderTheme,
|
||||
enableAnimation: _enableAnimation,
|
||||
textDirection: _textDirection,
|
||||
startThumbCenter: startThumbCenter,
|
||||
endThumbCenter: endThumbCenter,
|
||||
startThumbCenter: _startThumbCenter,
|
||||
endThumbCenter: _endThumbCenter,
|
||||
isDiscrete: isDiscrete,
|
||||
isEnabled: isEnabled,
|
||||
);
|
||||
@ -1327,7 +1329,7 @@ class _RenderRangeSlider extends RenderBox with RelayoutWhenSystemFontsChangeMix
|
||||
if (startThumbSelected) {
|
||||
_sliderTheme.overlayShape!.paint(
|
||||
context,
|
||||
startThumbCenter,
|
||||
_startThumbCenter,
|
||||
activationAnimation: _overlayAnimation,
|
||||
enableAnimation: _enableAnimation,
|
||||
isDiscrete: isDiscrete,
|
||||
@ -1343,7 +1345,7 @@ class _RenderRangeSlider extends RenderBox with RelayoutWhenSystemFontsChangeMix
|
||||
if (endThumbSelected) {
|
||||
_sliderTheme.overlayShape!.paint(
|
||||
context,
|
||||
endThumbCenter,
|
||||
_endThumbCenter,
|
||||
activationAnimation: _overlayAnimation,
|
||||
enableAnimation: _enableAnimation,
|
||||
isDiscrete: isDiscrete,
|
||||
@ -1381,21 +1383,21 @@ class _RenderRangeSlider extends RenderBox with RelayoutWhenSystemFontsChangeMix
|
||||
sliderTheme: _sliderTheme,
|
||||
enableAnimation: _enableAnimation,
|
||||
textDirection: _textDirection,
|
||||
startThumbCenter: startThumbCenter,
|
||||
endThumbCenter: endThumbCenter,
|
||||
startThumbCenter: _startThumbCenter,
|
||||
endThumbCenter: _endThumbCenter,
|
||||
isEnabled: isEnabled,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final double thumbDelta = (endThumbCenter.dx - startThumbCenter.dx).abs();
|
||||
final double thumbDelta = (_endThumbCenter.dx - _startThumbCenter.dx).abs();
|
||||
|
||||
final bool isLastThumbStart = _lastThumbSelection == Thumb.start;
|
||||
final Thumb bottomThumb = isLastThumbStart ? Thumb.end : Thumb.start;
|
||||
final Thumb topThumb = isLastThumbStart ? Thumb.start : Thumb.end;
|
||||
final Offset bottomThumbCenter = isLastThumbStart ? endThumbCenter : startThumbCenter;
|
||||
final Offset topThumbCenter = isLastThumbStart ? startThumbCenter : endThumbCenter;
|
||||
final Offset bottomThumbCenter = isLastThumbStart ? _endThumbCenter : _startThumbCenter;
|
||||
final Offset topThumbCenter = isLastThumbStart ? _startThumbCenter : _endThumbCenter;
|
||||
final TextPainter bottomLabelPainter = isLastThumbStart ? _endLabelPainter : _startLabelPainter;
|
||||
final TextPainter topLabelPainter = isLastThumbStart ? _startLabelPainter : _endLabelPainter;
|
||||
final double bottomValue = isLastThumbStart ? endValue : startValue;
|
||||
@ -1441,7 +1443,7 @@ class _RenderRangeSlider extends RenderBox with RelayoutWhenSystemFontsChangeMix
|
||||
if (shouldPaintValueIndicators) {
|
||||
final double startOffset = sliderTheme.rangeValueIndicatorShape!.getHorizontalShift(
|
||||
parentBox: this,
|
||||
center: startThumbCenter,
|
||||
center: _startThumbCenter,
|
||||
labelPainter: _startLabelPainter,
|
||||
activationAnimation: _valueIndicatorAnimation,
|
||||
textScaleFactor: textScaleFactor,
|
||||
@ -1449,7 +1451,7 @@ class _RenderRangeSlider extends RenderBox with RelayoutWhenSystemFontsChangeMix
|
||||
);
|
||||
final double endOffset = sliderTheme.rangeValueIndicatorShape!.getHorizontalShift(
|
||||
parentBox: this,
|
||||
center: endThumbCenter,
|
||||
center: _endThumbCenter,
|
||||
labelPainter: _endLabelPainter,
|
||||
activationAnimation: _valueIndicatorAnimation,
|
||||
textScaleFactor: textScaleFactor,
|
||||
@ -1575,8 +1577,16 @@ class _RenderRangeSlider extends RenderBox with RelayoutWhenSystemFontsChangeMix
|
||||
);
|
||||
|
||||
// Split the semantics node area between the start and end nodes.
|
||||
final Rect leftRect = Rect.fromPoints(node.rect.topLeft, node.rect.bottomCenter);
|
||||
final Rect rightRect = Rect.fromPoints(node.rect.topCenter, node.rect.bottomRight);
|
||||
final Rect leftRect = Rect.fromCenter(
|
||||
center: _startThumbCenter,
|
||||
width: kMinInteractiveDimension,
|
||||
height: kMinInteractiveDimension,
|
||||
);
|
||||
final Rect rightRect = Rect.fromCenter(
|
||||
center: _endThumbCenter,
|
||||
width: kMinInteractiveDimension,
|
||||
height: kMinInteractiveDimension,
|
||||
);
|
||||
switch (textDirection) {
|
||||
case TextDirection.ltr:
|
||||
_startSemanticsNode!.rect = leftRect;
|
||||
|
@ -1853,7 +1853,7 @@ void main() {
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('Range Slider Semantics', (WidgetTester tester) async {
|
||||
testWidgets('Range Slider Semantics - ltr', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: Theme(
|
||||
@ -1862,7 +1862,7 @@ void main() {
|
||||
textDirection: TextDirection.ltr,
|
||||
child: Material(
|
||||
child: RangeSlider(
|
||||
values: const RangeValues(10.0, 12.0),
|
||||
values: const RangeValues(10.0, 30.0),
|
||||
max: 100.0,
|
||||
onChanged: (RangeValues v) { },
|
||||
),
|
||||
@ -1874,8 +1874,9 @@ void main() {
|
||||
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final SemanticsNode semanticsNode = tester.getSemantics(find.byType(RangeSlider));
|
||||
expect(
|
||||
tester.getSemantics(find.byType(RangeSlider)),
|
||||
semanticsNode,
|
||||
matchesSemantics(
|
||||
scopesRoute: true,
|
||||
children:<Matcher>[
|
||||
@ -1888,7 +1889,91 @@ void main() {
|
||||
hasIncreaseAction: true,
|
||||
hasDecreaseAction: true,
|
||||
value: '10%',
|
||||
increasedValue: '10%',
|
||||
increasedValue: '15%',
|
||||
decreasedValue: '5%',
|
||||
rect: const Rect.fromLTRB(75.2, 276.0, 123.2, 324.0),
|
||||
),
|
||||
matchesSemantics(
|
||||
isEnabled: true,
|
||||
isSlider: true,
|
||||
hasEnabledState: true,
|
||||
hasIncreaseAction: true,
|
||||
hasDecreaseAction: true,
|
||||
value: '30%',
|
||||
increasedValue: '35%',
|
||||
decreasedValue: '25%',
|
||||
rect: const Rect.fromLTRB(225.6, 276.0, 273.6, 324.0),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
// TODO(tahatesser): This is a workaround for matching
|
||||
// the semantics node rects by avoiding floating point errors.
|
||||
// https://github.com/flutter/flutter/issues/115079
|
||||
// Get semantics node rects.
|
||||
final List<Rect> rects = <Rect>[];
|
||||
semanticsNode.visitChildren((SemanticsNode node) {
|
||||
node.visitChildren((SemanticsNode node) {
|
||||
// Round rect values to avoid floating point errors.
|
||||
rects.add(
|
||||
Rect.fromLTRB(
|
||||
node.rect.left.roundToDouble(),
|
||||
node.rect.top.roundToDouble(),
|
||||
node.rect.right.roundToDouble(),
|
||||
node.rect.bottom.roundToDouble(),
|
||||
),
|
||||
);
|
||||
return true;
|
||||
});
|
||||
return true;
|
||||
});
|
||||
// Test that the semantics node rect sizes are correct.
|
||||
expect(rects, <Rect>[
|
||||
const Rect.fromLTRB(75.0, 276.0, 123.0, 324.0),
|
||||
const Rect.fromLTRB(226.0, 276.0, 274.0, 324.0)
|
||||
]);
|
||||
});
|
||||
|
||||
testWidgets('Range Slider Semantics - rtl', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: Theme(
|
||||
data: ThemeData.light(),
|
||||
child: Directionality(
|
||||
textDirection: TextDirection.rtl,
|
||||
child: Material(
|
||||
child: RangeSlider(
|
||||
values: const RangeValues(10.0, 30.0),
|
||||
max: 100.0,
|
||||
onChanged: (RangeValues v) { },
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final SemanticsNode semanticsNode = tester.getSemantics(find.byType(RangeSlider));
|
||||
expect(
|
||||
semanticsNode,
|
||||
matchesSemantics(
|
||||
scopesRoute: true,
|
||||
children:<Matcher>[
|
||||
matchesSemantics(
|
||||
children: <Matcher>[
|
||||
matchesSemantics(
|
||||
isEnabled: true,
|
||||
isSlider: true,
|
||||
hasEnabledState: true,
|
||||
hasIncreaseAction: true,
|
||||
hasDecreaseAction: true,
|
||||
value: '10%',
|
||||
increasedValue: '15%',
|
||||
decreasedValue: '5%',
|
||||
),
|
||||
matchesSemantics(
|
||||
@ -1897,15 +1982,41 @@ void main() {
|
||||
hasEnabledState: true,
|
||||
hasIncreaseAction: true,
|
||||
hasDecreaseAction: true,
|
||||
value: '12%',
|
||||
increasedValue: '17%',
|
||||
decreasedValue: '12%',
|
||||
value: '30%',
|
||||
increasedValue: '35%',
|
||||
decreasedValue: '25%',
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
// TODO(tahatesser): This is a workaround for matching
|
||||
// the semantics node rects by avoiding floating point errors.
|
||||
// https://github.com/flutter/flutter/issues/115079
|
||||
// Get semantics node rects.
|
||||
final List<Rect> rects = <Rect>[];
|
||||
semanticsNode.visitChildren((SemanticsNode node) {
|
||||
node.visitChildren((SemanticsNode node) {
|
||||
// Round rect values to avoid floating point errors.
|
||||
rects.add(
|
||||
Rect.fromLTRB(
|
||||
node.rect.left.roundToDouble(),
|
||||
node.rect.top.roundToDouble(),
|
||||
node.rect.right.roundToDouble(),
|
||||
node.rect.bottom.roundToDouble(),
|
||||
),
|
||||
);
|
||||
return true;
|
||||
});
|
||||
return true;
|
||||
});
|
||||
// Test that the semantics node rect sizes are correct.
|
||||
expect(rects, <Rect>[
|
||||
const Rect.fromLTRB(526.0, 276.0, 574.0, 324.0),
|
||||
const Rect.fromLTRB(677.0, 276.0, 725.0, 324.0)
|
||||
]);
|
||||
});
|
||||
|
||||
testWidgets('Range Slider implements debugFillProperties', (WidgetTester tester) async {
|
||||
|
Loading…
x
Reference in New Issue
Block a user