[release] Revert "Fix `Slider` semantic node size (#115285)" (#116294) (#116296)
This reverts commit 8473da22cde2fcedd51af654822cac83a9b5ecb5.
diff --git a/packages/flutter/lib/src/material/slider.dart b/packages/flutter/lib/src/material/slider.dart
index feb77cd..f9abab6 100644
--- a/packages/flutter/lib/src/material/slider.dart
+++ b/packages/flutter/lib/src/material/slider.dart
@@ -821,11 +821,22 @@
// in range_slider.dart.
Size screenSize() => MediaQuery.of(context).size;
- void handleDidGainAccessibilityFocus() {
- // Automatically activate the slider when it receives a11y focus.
- if (!focusNode.hasFocus && focusNode.canRequestFocus) {
- focusNode.requestFocus();
- }
+ VoidCallback? handleDidGainAccessibilityFocus;
+ switch (theme.platform) {
+ case TargetPlatform.android:
+ case TargetPlatform.fuchsia:
+ case TargetPlatform.iOS:
+ case TargetPlatform.linux:
+ case TargetPlatform.macOS:
+ break;
+ case TargetPlatform.windows:
+ handleDidGainAccessibilityFocus = () {
+ // Automatically activate the slider when it receives a11y focus.
+ if (!focusNode.hasFocus && focusNode.canRequestFocus) {
+ focusNode.requestFocus();
+ }
+ };
+ break;
}
final Map<ShortcutActivator, Intent> shortcutMap;
@@ -846,35 +857,38 @@
? math.min(MediaQuery.of(context).textScaleFactor, 1.3)
: MediaQuery.of(context).textScaleFactor;
- return FocusableActionDetector(
- actions: _actionMap,
- shortcuts: shortcutMap,
- focusNode: focusNode,
- autofocus: widget.autofocus,
- enabled: _enabled,
- onShowFocusHighlight: _handleFocusHighlightChanged,
- onShowHoverHighlight: _handleHoverChanged,
- mouseCursor: effectiveMouseCursor,
- includeFocusSemantics: false,
- child: CompositedTransformTarget(
- link: _layerLink,
- child: _SliderRenderObjectWidget(
- key: _renderObjectKey,
- value: _convert(widget.value),
- secondaryTrackValue: (widget.secondaryTrackValue != null) ? _convert(widget.secondaryTrackValue!) : null,
- divisions: widget.divisions,
- label: widget.label,
- sliderTheme: sliderTheme,
- textScaleFactor: textScaleFactor,
- screenSize: screenSize(),
- onChanged: (widget.onChanged != null) && (widget.max > widget.min) ? _handleChanged : null,
- onChangeStart: _handleDragStart,
- onChangeEnd: _handleDragEnd,
- state: this,
- semanticFormatterCallback: widget.semanticFormatterCallback,
- onDidGainAccessibilityFocus: handleDidGainAccessibilityFocus,
- hasFocus: _focused,
- hovering: _hovering,
+ return Semantics(
+ container: true,
+ slider: true,
+ onDidGainAccessibilityFocus: handleDidGainAccessibilityFocus,
+ child: FocusableActionDetector(
+ actions: _actionMap,
+ shortcuts: shortcutMap,
+ focusNode: focusNode,
+ autofocus: widget.autofocus,
+ enabled: _enabled,
+ onShowFocusHighlight: _handleFocusHighlightChanged,
+ onShowHoverHighlight: _handleHoverChanged,
+ mouseCursor: effectiveMouseCursor,
+ child: CompositedTransformTarget(
+ link: _layerLink,
+ child: _SliderRenderObjectWidget(
+ key: _renderObjectKey,
+ value: _convert(widget.value),
+ secondaryTrackValue: (widget.secondaryTrackValue != null) ? _convert(widget.secondaryTrackValue!) : null,
+ divisions: widget.divisions,
+ label: widget.label,
+ sliderTheme: sliderTheme,
+ textScaleFactor: textScaleFactor,
+ screenSize: screenSize(),
+ onChanged: (widget.onChanged != null) && (widget.max > widget.min) ? _handleChanged : null,
+ onChangeStart: _handleDragStart,
+ onChangeEnd: _handleDragEnd,
+ state: this,
+ semanticFormatterCallback: widget.semanticFormatterCallback,
+ hasFocus: _focused,
+ hovering: _hovering,
+ ),
),
),
);
@@ -935,7 +949,6 @@
required this.onChangeEnd,
required this.state,
required this.semanticFormatterCallback,
- required this.onDidGainAccessibilityFocus,
required this.hasFocus,
required this.hovering,
});
@@ -951,7 +964,6 @@
final ValueChanged<double>? onChangeStart;
final ValueChanged<double>? onChangeEnd;
final SemanticFormatterCallback? semanticFormatterCallback;
- final VoidCallback? onDidGainAccessibilityFocus;
final _SliderState state;
final bool hasFocus;
final bool hovering;
@@ -972,7 +984,6 @@
state: state,
textDirection: Directionality.of(context),
semanticFormatterCallback: semanticFormatterCallback,
- onDidGainAccessibilityFocus: onDidGainAccessibilityFocus,
platform: Theme.of(context).platform,
hasFocus: hasFocus,
hovering: hovering,
@@ -997,7 +1008,6 @@
..onChangeEnd = onChangeEnd
..textDirection = Directionality.of(context)
..semanticFormatterCallback = semanticFormatterCallback
- ..onDidGainAccessibilityFocus = onDidGainAccessibilityFocus
..platform = Theme.of(context).platform
..hasFocus = hasFocus
..hovering = hovering
@@ -1019,7 +1029,6 @@
required TargetPlatform platform,
required ValueChanged<double>? onChanged,
required SemanticFormatterCallback? semanticFormatterCallback,
- required this.onDidGainAccessibilityFocus,
required this.onChangeStart,
required this.onChangeEnd,
required _SliderState state,
@@ -1105,7 +1114,6 @@
bool _active = false;
double _currentDragValue = 0.0;
Rect? overlayRect;
- late Offset _thumbCenter;
// This rect is used in gesture calculations, where the gesture coordinates
// are relative to the sliders origin. Therefore, the offset is passed as
@@ -1251,7 +1259,6 @@
}
}
- VoidCallback? onDidGainAccessibilityFocus;
ValueChanged<double>? onChangeStart;
ValueChanged<double>? onChangeEnd;
@@ -1575,10 +1582,10 @@
sliderTheme: _sliderTheme,
isDiscrete: isDiscrete,
);
- _thumbCenter = Offset(trackRect.left + visualPosition * trackRect.width, trackRect.center.dy);
+ final Offset thumbCenter = Offset(trackRect.left + visualPosition * trackRect.width, trackRect.center.dy);
if (isInteractive) {
final Size overlaySize = sliderTheme.overlayShape!.getPreferredSize(isInteractive, false);
- overlayRect = Rect.fromCircle(center: _thumbCenter, radius: overlaySize.width / 2.0);
+ overlayRect = Rect.fromCircle(center: thumbCenter, radius: overlaySize.width / 2.0);
}
final Offset? secondaryOffset = (secondaryVisualPosition != null) ? Offset(trackRect.left + secondaryVisualPosition * trackRect.width, trackRect.center.dy) : null;
@@ -1589,7 +1596,7 @@
sliderTheme: _sliderTheme,
enableAnimation: _enableAnimation,
textDirection: _textDirection,
- thumbCenter: _thumbCenter,
+ thumbCenter: thumbCenter,
secondaryOffset: secondaryOffset,
isDiscrete: isDiscrete,
isEnabled: isInteractive,
@@ -1598,7 +1605,7 @@
if (!_overlayAnimation.isDismissed) {
_sliderTheme.overlayShape!.paint(
context,
- _thumbCenter,
+ thumbCenter,
activationAnimation: _overlayAnimation,
enableAnimation: _enableAnimation,
isDiscrete: isDiscrete,
@@ -1635,7 +1642,7 @@
sliderTheme: _sliderTheme,
enableAnimation: _enableAnimation,
textDirection: _textDirection,
- thumbCenter: _thumbCenter,
+ thumbCenter: thumbCenter,
isEnabled: isInteractive,
);
}
@@ -1648,7 +1655,7 @@
if (attached) {
_sliderTheme.valueIndicatorShape!.paint(
context,
- offset + _thumbCenter,
+ offset + thumbCenter,
activationAnimation: _valueIndicatorAnimation,
enableAnimation: _enableAnimation,
isDiscrete: isDiscrete,
@@ -1667,7 +1674,7 @@
_sliderTheme.thumbShape!.paint(
context,
- _thumbCenter,
+ thumbCenter,
activationAnimation: _overlayAnimation,
enableAnimation: _enableAnimation,
isDiscrete: isDiscrete,
@@ -1682,22 +1689,11 @@
}
@override
- void assembleSemanticsNode(SemanticsNode node, SemanticsConfiguration config, Iterable<SemanticsNode> children) {
- node.rect = Rect.fromCenter(
- center: _thumbCenter,
- width: kMinInteractiveDimension,
- height: kMinInteractiveDimension,
- );
-
- node.updateWith(config: config);
- }
-
- @override
void describeSemanticsConfiguration(SemanticsConfiguration config) {
super.describeSemanticsConfiguration(config);
// The Slider widget has its own Focus widget with semantics information,
- // and want that semantics node to collect the semantics information here
+ // and we want that semantics node to collect the semantics information here
// so that it's all in the same node: otherwise Talkback sees that the node
// has focusable children, and it won't focus the Slider's Focus widget
// because it thinks the Focus widget's node doesn't have anything to say
@@ -1705,23 +1701,9 @@
// information into one node means that Talkback will recognize that it has
// something to say and focus it when it receives keyboard focus.
// (See https://github.com/flutter/flutter/issues/57038 for context).
- config.isSemanticBoundary = true;
+ config.isSemanticBoundary = false;
config.isEnabled = isInteractive;
- config.isSlider = true;
- config.isFocusable = isInteractive;
- config.isFocused = hasFocus;
- switch (_platform) {
- case TargetPlatform.android:
- case TargetPlatform.fuchsia:
- case TargetPlatform.iOS:
- case TargetPlatform.linux:
- case TargetPlatform.macOS:
- break;
- case TargetPlatform.windows:
- config.onDidGainAccessibilityFocus = onDidGainAccessibilityFocus;
- break;
- }
config.textDirection = textDirection;
if (isInteractive) {
config.onIncrease = increaseAction;
diff --git a/packages/flutter/test/material/slider_test.dart b/packages/flutter/test/material/slider_test.dart
index ba31580..84e5593 100644
--- a/packages/flutter/test/material/slider_test.dart
+++ b/packages/flutter/test/material/slider_test.dart
@@ -15,6 +15,7 @@
import 'package:flutter_test/flutter_test.dart';
import '../rendering/mock_canvas.dart';
+import '../widgets/semantics_tester.dart';
// A thumb shape that also logs its repaint center.
class LoggingThumbShape extends SliderComponentShape {
@@ -1147,6 +1148,8 @@
});
testWidgets('Slider Semantics', (WidgetTester tester) async {
+ final SemanticsTester semantics = SemanticsTester(tester);
+
await tester.pumpWidget(MaterialApp(
home: Directionality(
textDirection: TextDirection.ltr,
@@ -1161,24 +1164,49 @@
await tester.pumpAndSettle();
- SemanticsNode semanticsNode = tester.getSemantics(find.byType(Slider));
expect(
- semanticsNode,
- matchesSemantics(
- children: <Matcher>[
- matchesSemantics(
- isEnabled: true,
- isSlider: true,
- isFocusable: true,
- hasEnabledState: true,
- hasIncreaseAction: true,
- hasDecreaseAction: true,
- value: '50%',
- increasedValue: '55%',
- decreasedValue: '45%',
- textDirection: TextDirection.ltr,
- ),
- ],
+ semantics,
+ hasSemantics(
+ TestSemantics.root(
+ children: <TestSemantics>[
+ TestSemantics(
+ id: 1,
+ textDirection: TextDirection.ltr,
+ children: <TestSemantics>[
+ TestSemantics(
+ id: 2,
+ children: <TestSemantics>[
+ TestSemantics(
+ id: 3,
+ flags: <SemanticsFlag>[SemanticsFlag.scopesRoute],
+ children: <TestSemantics>[
+ TestSemantics(
+ id: 4,
+ flags: <SemanticsFlag>[
+ SemanticsFlag.hasEnabledState,
+ SemanticsFlag.isEnabled,
+ SemanticsFlag.isFocusable,
+ SemanticsFlag.isSlider,
+ ],
+ actions: <SemanticsAction>[
+ SemanticsAction.increase,
+ SemanticsAction.decrease,
+ ],
+ value: '50%',
+ increasedValue: '55%',
+ decreasedValue: '45%',
+ textDirection: TextDirection.ltr,
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ ),
+ ignoreRect: true,
+ ignoreTransform: true,
),
);
@@ -1195,27 +1223,95 @@
),
));
- await tester.pump();
- semanticsNode = tester.getSemantics(find.byType(Slider));
expect(
- semanticsNode,
- matchesSemantics(
- scopesRoute: true,
- children: <Matcher>[
- matchesSemantics(
- isSlider: true,
- hasEnabledState: true,
- value: '50%',
- increasedValue: '55%',
- decreasedValue: '45%',
- textDirection: TextDirection.ltr,
- ),
- ],
+ semantics,
+ hasSemantics(
+ TestSemantics.root(
+ children: <TestSemantics>[
+ TestSemantics(
+ id: 1,
+ textDirection: TextDirection.ltr,
+ children: <TestSemantics>[
+ TestSemantics(
+ id: 2,
+ children: <TestSemantics>[
+ TestSemantics(
+ id: 3,
+ flags: <SemanticsFlag>[SemanticsFlag.scopesRoute],
+ children: <TestSemantics>[
+ TestSemantics(
+ id: 4,
+ flags: <SemanticsFlag>[
+ SemanticsFlag.hasEnabledState,
+ // isFocusable is delayed by 1 frame.
+ SemanticsFlag.isFocusable,
+ SemanticsFlag.isSlider,
+ ],
+ value: '50%',
+ increasedValue: '55%',
+ decreasedValue: '45%',
+ textDirection: TextDirection.ltr,
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ ),
+ ignoreRect: true,
+ ignoreTransform: true,
),
);
+
+ await tester.pump();
+ expect(
+ semantics,
+ hasSemantics(
+ TestSemantics.root(
+ children: <TestSemantics>[
+ TestSemantics(
+ id: 1,
+ textDirection: TextDirection.ltr,
+ children: <TestSemantics>[
+ TestSemantics(
+ id: 2,
+ children: <TestSemantics>[
+ TestSemantics(
+ id: 3,
+ flags: <SemanticsFlag>[SemanticsFlag.scopesRoute],
+ children: <TestSemantics>[
+ TestSemantics(
+ id: 4,
+ flags: <SemanticsFlag>[
+ SemanticsFlag.hasEnabledState,
+ SemanticsFlag.isSlider,
+ ],
+ value: '50%',
+ increasedValue: '55%',
+ decreasedValue: '45%',
+ textDirection: TextDirection.ltr,
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ ),
+ ignoreRect: true,
+ ignoreTransform: true,
+ ),
+ );
+
+ semantics.dispose();
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android, TargetPlatform.fuchsia, TargetPlatform.linux }));
testWidgets('Slider Semantics', (WidgetTester tester) async {
+ final SemanticsTester semantics = SemanticsTester(tester);
+
await tester.pumpWidget(
MaterialApp(
home: Theme(
@@ -1234,26 +1330,41 @@
),
);
- await tester.pumpAndSettle();
-
- SemanticsNode semanticsNode = tester.getSemantics(find.byType(Slider));
expect(
- semanticsNode,
- matchesSemantics(
- children: <Matcher>[
- matchesSemantics(
- isEnabled: true,
- isSlider: true,
- isFocusable: true,
- hasEnabledState: true,
- hasIncreaseAction: true,
- hasDecreaseAction: true,
- value: '50%',
- increasedValue: '60%',
- decreasedValue: '40%',
- textDirection: TextDirection.ltr,
- ),
- ],
+ semantics,
+ hasSemantics(
+ TestSemantics.root(
+ children: <TestSemantics>[
+ TestSemantics(
+ id: 1,
+ textDirection: TextDirection.ltr,
+ children: <TestSemantics>[
+ TestSemantics(
+ id: 2,
+ children: <TestSemantics>[
+ TestSemantics(
+ id: 3,
+ flags: <SemanticsFlag>[SemanticsFlag.scopesRoute],
+ children: <TestSemantics>[
+ TestSemantics(
+ id: 4,
+ flags: <SemanticsFlag>[SemanticsFlag.hasEnabledState, SemanticsFlag.isEnabled, SemanticsFlag.isFocusable, SemanticsFlag.isSlider],
+ actions: <SemanticsAction>[SemanticsAction.increase, SemanticsAction.decrease],
+ value: '50%',
+ increasedValue: '60%',
+ decreasedValue: '40%',
+ textDirection: TextDirection.ltr,
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ ),
+ ignoreRect: true,
+ ignoreTransform: true,
),
);
@@ -1270,26 +1381,48 @@
),
));
- semanticsNode = tester.getSemantics(find.byType(Slider));
expect(
- semanticsNode,
- matchesSemantics(
- scopesRoute: true,
- children: <Matcher>[
- matchesSemantics(
- isSlider: true,
- hasEnabledState: true,
- value: '50%',
- increasedValue: '60%',
- decreasedValue: '40%',
- textDirection: TextDirection.ltr,
- ),
- ],
+ semantics,
+ hasSemantics(
+ TestSemantics.root(
+ children: <TestSemantics>[
+ TestSemantics(
+ id: 1,
+ textDirection: TextDirection.ltr,
+ children: <TestSemantics>[
+ TestSemantics(
+ id: 2,
+ children: <TestSemantics>[
+ TestSemantics(
+ id: 3,
+ flags: <SemanticsFlag>[SemanticsFlag.scopesRoute],
+ children: <TestSemantics>[
+ TestSemantics(
+ id: 5,
+ flags: <SemanticsFlag>[SemanticsFlag.hasEnabledState, SemanticsFlag.isSlider],
+ value: '50%',
+ increasedValue: '60%',
+ decreasedValue: '40%',
+ textDirection: TextDirection.ltr,
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ ),
+ ignoreRect: true,
+ ignoreTransform: true,
),
);
+ semantics.dispose();
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets('Slider Semantics', (WidgetTester tester) async {
+ final SemanticsTester semantics = SemanticsTester(tester);
+
await tester.pumpWidget(MaterialApp(
home: Directionality(
textDirection: TextDirection.ltr,
@@ -1304,25 +1437,50 @@
await tester.pumpAndSettle();
- SemanticsNode semanticsNode = tester.getSemantics(find.byType(Slider));
expect(
- semanticsNode,
- matchesSemantics(
- children: <Matcher>[
- matchesSemantics(
- isEnabled: true,
- isSlider: true,
- isFocusable: true,
- hasEnabledState: true,
- hasIncreaseAction: true,
- hasDecreaseAction: true,
- hasDidGainAccessibilityFocusAction: true,
- value: '50%',
- increasedValue: '55%',
- decreasedValue: '45%',
- textDirection: TextDirection.ltr,
- ),
- ],
+ semantics,
+ hasSemantics(
+ TestSemantics.root(
+ children: <TestSemantics>[
+ TestSemantics(
+ id: 1,
+ textDirection: TextDirection.ltr,
+ children: <TestSemantics>[
+ TestSemantics(
+ id: 2,
+ children: <TestSemantics>[
+ TestSemantics(
+ id: 3,
+ flags: <SemanticsFlag>[SemanticsFlag.scopesRoute],
+ children: <TestSemantics>[
+ TestSemantics(
+ id: 4,
+ flags: <SemanticsFlag>[
+ SemanticsFlag.hasEnabledState,
+ SemanticsFlag.isEnabled,
+ SemanticsFlag.isFocusable,
+ SemanticsFlag.isSlider,
+ ],
+ actions: <SemanticsAction>[
+ SemanticsAction.increase,
+ SemanticsAction.decrease,
+ SemanticsAction.didGainAccessibilityFocus,
+ ],
+ value: '50%',
+ increasedValue: '55%',
+ decreasedValue: '45%',
+ textDirection: TextDirection.ltr,
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ ),
+ ignoreRect: true,
+ ignoreTransform: true,
),
);
@@ -1339,28 +1497,101 @@
),
));
- await tester.pump();
- semanticsNode = tester.getSemantics(find.byType(Slider));
expect(
- semanticsNode,
- matchesSemantics(
- scopesRoute: true,
- children: <Matcher>[
- matchesSemantics(
- isSlider: true,
- hasEnabledState: true,
- hasDidGainAccessibilityFocusAction: true,
- value: '50%',
- increasedValue: '55%',
- decreasedValue: '45%',
- textDirection: TextDirection.ltr,
- ),
- ],
+ semantics,
+ hasSemantics(
+ TestSemantics.root(
+ children: <TestSemantics>[
+ TestSemantics(
+ id: 1,
+ textDirection: TextDirection.ltr,
+ children: <TestSemantics>[
+ TestSemantics(
+ id: 2,
+ children: <TestSemantics>[
+ TestSemantics(
+ id: 3,
+ flags: <SemanticsFlag>[SemanticsFlag.scopesRoute],
+ children: <TestSemantics>[
+ TestSemantics(
+ id: 4,
+ flags: <SemanticsFlag>[
+ SemanticsFlag.hasEnabledState,
+ // isFocusable is delayed by 1 frame.
+ SemanticsFlag.isFocusable,
+ SemanticsFlag.isSlider,
+ ],
+ actions: <SemanticsAction>[
+ SemanticsAction.didGainAccessibilityFocus,
+ ],
+ value: '50%',
+ increasedValue: '55%',
+ decreasedValue: '45%',
+ textDirection: TextDirection.ltr,
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ ),
+ ignoreRect: true,
+ ignoreTransform: true,
),
);
+
+ await tester.pump();
+ expect(
+ semantics,
+ hasSemantics(
+ TestSemantics.root(
+ children: <TestSemantics>[
+ TestSemantics(
+ id: 1,
+ textDirection: TextDirection.ltr,
+ children: <TestSemantics>[
+ TestSemantics(
+ id: 2,
+ children: <TestSemantics>[
+ TestSemantics(
+ id: 3,
+ flags: <SemanticsFlag>[SemanticsFlag.scopesRoute],
+ children: <TestSemantics>[
+ TestSemantics(
+ id: 4,
+ flags: <SemanticsFlag>[
+ SemanticsFlag.hasEnabledState,
+ SemanticsFlag.isSlider,
+ ],
+ actions: <SemanticsAction>[
+ SemanticsAction.didGainAccessibilityFocus,
+ ],
+ value: '50%',
+ increasedValue: '55%',
+ decreasedValue: '45%',
+ textDirection: TextDirection.ltr,
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ ),
+ ignoreRect: true,
+ ignoreTransform: true,
+ ),
+ );
+
+ semantics.dispose();
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.windows }));
testWidgets('Slider semantics with custom formatter', (WidgetTester tester) async {
+ final SemanticsTester semantics = SemanticsTester(tester);
+
await tester.pumpWidget(MaterialApp(
home: Directionality(
textDirection: TextDirection.ltr,
@@ -1376,32 +1607,50 @@
),
));
- await tester.pumpAndSettle();
-
- final SemanticsNode semanticsNode = tester.getSemantics(find.byType(Slider));
expect(
- semanticsNode,
- matchesSemantics(
- children: <Matcher>[
- matchesSemantics(
- isEnabled: true,
- isSlider: true,
- isFocusable: true,
- hasEnabledState: true,
- hasIncreaseAction: true,
- hasDecreaseAction: true,
- value: '40',
- increasedValue: '60',
- decreasedValue: '20',
- textDirection: TextDirection.ltr,
- ),
- ],
+ semantics,
+ hasSemantics(
+ TestSemantics.root(
+ children: <TestSemantics>[
+ TestSemantics(
+ id: 1,
+ textDirection: TextDirection.ltr,
+ children: <TestSemantics>[
+ TestSemantics(
+ id: 2,
+ children: <TestSemantics>[
+ TestSemantics(
+ id: 3,
+ flags: <SemanticsFlag>[SemanticsFlag.scopesRoute],
+ children: <TestSemantics>[
+ TestSemantics(
+ id: 4,
+ flags: <SemanticsFlag>[SemanticsFlag.hasEnabledState, SemanticsFlag.isEnabled, SemanticsFlag.isFocusable, SemanticsFlag.isSlider],
+ actions: <SemanticsAction>[SemanticsAction.increase, SemanticsAction.decrease],
+ value: '40',
+ increasedValue: '60',
+ decreasedValue: '20',
+ textDirection: TextDirection.ltr,
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ ),
+ ignoreRect: true,
+ ignoreTransform: true,
),
);
+ semantics.dispose();
});
// Regression test for https://github.com/flutter/flutter/issues/101868
testWidgets('Slider.label info should not write to semantic node', (WidgetTester tester) async {
+ final SemanticsTester semantics = SemanticsTester(tester);
+
await tester.pumpWidget(MaterialApp(
home: Directionality(
textDirection: TextDirection.ltr,
@@ -1418,28 +1667,44 @@
),
));
- await tester.pumpAndSettle();
-
- final SemanticsNode semanticsNode = tester.getSemantics(find.byType(Slider));
expect(
- semanticsNode,
- matchesSemantics(
- children: <Matcher>[
- matchesSemantics(
- isEnabled: true,
- isSlider: true,
- isFocusable: true,
- hasEnabledState: true,
- hasIncreaseAction: true,
- hasDecreaseAction: true,
- value: '40',
- increasedValue: '60',
- decreasedValue: '20',
- textDirection: TextDirection.ltr,
- ),
- ],
+ semantics,
+ hasSemantics(
+ TestSemantics.root(
+ children: <TestSemantics>[
+ TestSemantics(
+ id: 1,
+ textDirection: TextDirection.ltr,
+ children: <TestSemantics>[
+ TestSemantics(
+ id: 2,
+ children: <TestSemantics>[
+ TestSemantics(
+ id: 3,
+ flags: <SemanticsFlag>[SemanticsFlag.scopesRoute],
+ children: <TestSemantics>[
+ TestSemantics(
+ id: 4,
+ flags: <SemanticsFlag>[SemanticsFlag.hasEnabledState, SemanticsFlag.isEnabled, SemanticsFlag.isFocusable, SemanticsFlag.isSlider],
+ actions: <SemanticsAction>[SemanticsAction.increase, SemanticsAction.decrease],
+ value: '40',
+ increasedValue: '60',
+ decreasedValue: '20',
+ textDirection: TextDirection.ltr,
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ ),
+ ignoreRect: true,
+ ignoreTransform: true,
),
);
+ semantics.dispose();
});
testWidgets('Slider is focusable and has correct focus color', (WidgetTester tester) async {
@@ -2111,6 +2376,7 @@
});
testWidgets('Slider gains keyboard focus when it gains semantics focus on Windows', (WidgetTester tester) async {
+ final SemanticsTester semantics = SemanticsTester(tester);
final SemanticsOwner semanticsOwner = tester.binding.pipelineOwner.semanticsOwner!;
final FocusNode focusNode = FocusNode();
await tester.pumpWidget(
@@ -2125,32 +2391,55 @@
),
);
- final SemanticsNode semanticsNode = tester.getSemantics(find.byType(Slider));
- expect(
- semanticsNode,
- matchesSemantics(
- children: <Matcher>[
- matchesSemantics(
- isEnabled: true,
- isSlider: true,
- isFocusable: true,
- hasEnabledState: true,
- hasIncreaseAction: true,
- hasDecreaseAction: true,
- hasDidGainAccessibilityFocusAction: true,
- value: '50%',
- increasedValue: '55%',
- decreasedValue: '45%',
+ expect(semantics, hasSemantics(
+ TestSemantics.root(
+ children: <TestSemantics>[
+ TestSemantics(
+ id: 1,
textDirection: TextDirection.ltr,
+ children: <TestSemantics>[
+ TestSemantics(
+ id: 2,
+ children: <TestSemantics>[
+ TestSemantics(
+ id: 3,
+ flags: <SemanticsFlag>[SemanticsFlag.scopesRoute],
+ children: <TestSemantics>[
+ TestSemantics(
+ id: 4,
+ flags: <SemanticsFlag>[
+ SemanticsFlag.hasEnabledState,
+ SemanticsFlag.isEnabled,
+ SemanticsFlag.isFocusable,
+ SemanticsFlag.isSlider,
+ ],
+ actions: <SemanticsAction>[
+ SemanticsAction.increase,
+ SemanticsAction.decrease,
+ SemanticsAction.didGainAccessibilityFocus,
+ ],
+ value: '50%',
+ increasedValue: '55%',
+ decreasedValue: '45%',
+ textDirection: TextDirection.ltr,
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
),
],
),
- );
+ ignoreRect: true,
+ ignoreTransform: true,
+ ));
expect(focusNode.hasFocus, isFalse);
- semanticsOwner.performAction(5, SemanticsAction.didGainAccessibilityFocus);
+ semanticsOwner.performAction(4, SemanticsAction.didGainAccessibilityFocus);
await tester.pumpAndSettle();
expect(focusNode.hasFocus, isTrue);
+ semantics.dispose();
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.windows }));
testWidgets('Value indicator appears when it should', (WidgetTester tester) async {
diff --git a/packages/flutter/test/widgets/semantics_debugger_test.dart b/packages/flutter/test/widgets/semantics_debugger_test.dart
index 1de96fd..7dd740a 100644
--- a/packages/flutter/test/widgets/semantics_debugger_test.dart
+++ b/packages/flutter/test/widgets/semantics_debugger_test.dart
@@ -290,7 +290,7 @@
});
testWidgets('SemanticsDebugger slider', (WidgetTester tester) async {
- double value = 0.50;
+ double value = 0.75;
await tester.pumpWidget(
Directionality(
@@ -322,7 +322,7 @@
// interpreted as a gesture by the semantics debugger and sent to the widget
// as a semantic action that always moves by 10% of the complete track.
await tester.fling(find.byType(Slider), const Offset(-100.0, 0.0), 2000.0, warnIfMissed: false); // hitting the debugger
- expect(value, equals(0.45));
+ expect(value, equals(0.70));
});
testWidgets('SemanticsDebugger checkbox', (WidgetTester tester) async {
diff --git a/packages/flutter_test/test/controller_test.dart b/packages/flutter_test/test/controller_test.dart
index fc35c43..d4b532b 100644
--- a/packages/flutter_test/test/controller_test.dart
+++ b/packages/flutter_test/test/controller_test.dart
@@ -865,7 +865,7 @@
await tester.pumpWidget(const MaterialApp(home: _SemanticsTestWidget()));
// We're expecting the traversal to start where the slider is.
- final List<Matcher> expectedMatchers = <Matcher>[...fullTraversalMatchers]..removeRange(0, 7);
+ final List<Matcher> expectedMatchers = <Matcher>[...fullTraversalMatchers]..removeRange(0, 8);
expect(
tester.semantics.simulatedAccessibilityTraversal(start: find.byType(Slider)),
@@ -887,7 +887,7 @@
await tester.pumpWidget(const MaterialApp(home: _SemanticsTestWidget()));
// We're expecting the traversal to end where the slider is, inclusive.
- final Iterable<Matcher> expectedMatchers = <Matcher>[...fullTraversalMatchers].getRange(0, 8);
+ final Iterable<Matcher> expectedMatchers = <Matcher>[...fullTraversalMatchers].getRange(0, 9);
expect(
tester.semantics.simulatedAccessibilityTraversal(end: find.byType(Slider)),
@@ -909,7 +909,7 @@
await tester.pumpWidget(const MaterialApp(home: _SemanticsTestWidget()));
// We're expecting the traversal to start at the text field and end at the slider.
- final Iterable<Matcher> expectedMatchers = <Matcher>[...fullTraversalMatchers].getRange(1, 8);
+ final Iterable<Matcher> expectedMatchers = <Matcher>[...fullTraversalMatchers].getRange(1, 9);
expect(
tester.semantics.simulatedAccessibilityTraversal(