Unverified Commit 3a40d0ee authored by Michael Goderbauer's avatar Michael Goderbauer Committed by GitHub

Support SemanticsFlag for Header (#15255)

parent 96ce9d64
...@@ -152,9 +152,12 @@ class GalleryHomeState extends State<GalleryHome> with SingleTickerProviderState ...@@ -152,9 +152,12 @@ class GalleryHomeState extends State<GalleryHome> with SingleTickerProviderState
child: new SafeArea( child: new SafeArea(
top: false, top: false,
bottom: false, bottom: false,
child: new Semantics(
header: true,
child: new Text(galleryItem.category, style: headerStyle), child: new Text(galleryItem.category, style: headerStyle),
), ),
), ),
),
) )
); );
category = galleryItem.category; category = galleryItem.category;
......
...@@ -817,6 +817,21 @@ class RenderCustomPaint extends RenderProxyBox { ...@@ -817,6 +817,21 @@ class RenderCustomPaint extends RenderProxyBox {
if (properties.button != null) { if (properties.button != null) {
config.isButton = properties.button; config.isButton = properties.button;
} }
if (properties.textField != null) {
config.isTextField = properties.textField;
}
if (properties.focused != null) {
config.isFocused = properties.focused;
}
if (properties.enabled != null) {
config.isEnabled = properties.enabled;
}
if (properties.inMutuallyExclusiveGroup != null) {
config.isInMutuallyExclusiveGroup = properties.inMutuallyExclusiveGroup;
}
if (properties.header != null) {
config.isHeader = properties.header;
}
if (properties.label != null) { if (properties.label != null) {
config.label = properties.label; config.label = properties.label;
} }
......
...@@ -3015,6 +3015,10 @@ class RenderSemanticsAnnotations extends RenderProxyBox { ...@@ -3015,6 +3015,10 @@ class RenderSemanticsAnnotations extends RenderProxyBox {
bool checked, bool checked,
bool selected, bool selected,
bool button, bool button,
bool header,
bool textField,
bool focused,
bool inMutuallyExclusiveGroup,
String label, String label,
String value, String value,
String increasedValue, String increasedValue,
...@@ -3045,6 +3049,10 @@ class RenderSemanticsAnnotations extends RenderProxyBox { ...@@ -3045,6 +3049,10 @@ class RenderSemanticsAnnotations extends RenderProxyBox {
_checked = checked, _checked = checked,
_selected = selected, _selected = selected,
_button = button, _button = button,
_header = header,
_textField = textField,
_focused = focused,
_inMutuallyExclusiveGroup = inMutuallyExclusiveGroup,
_label = label, _label = label,
_value = value, _value = value,
_increasedValue = increasedValue, _increasedValue = increasedValue,
...@@ -3152,6 +3160,47 @@ class RenderSemanticsAnnotations extends RenderProxyBox { ...@@ -3152,6 +3160,47 @@ class RenderSemanticsAnnotations extends RenderProxyBox {
markNeedsSemanticsUpdate(); markNeedsSemanticsUpdate();
} }
/// If non-null, sets the [SemanticsNode.isHeader] semantic to the given value.
bool get header => _header;
bool _header;
set header(bool value) {
if (header == value)
return;
_header = value;
markNeedsSemanticsUpdate();
}
/// If non-null, sets the [SemanticsNode.isTextField] semantic to the given value.
bool get textField => _textField;
bool _textField;
set textField(bool value) {
if (textField == value)
return;
_textField = value;
markNeedsSemanticsUpdate();
}
/// If non-null, sets the [SemanticsNode.isFocused] semantic to the given value.
bool get focused => _focused;
bool _focused;
set focused(bool value) {
if (focused == value)
return;
_focused = value;
markNeedsSemanticsUpdate();
}
/// If non-null, sets the [SemanticsNode.isInMutuallyExclusiveGroup] semantic
/// to the given value.
bool get inMutuallyExclusiveGroup => _inMutuallyExclusiveGroup;
bool _inMutuallyExclusiveGroup;
set inMutuallyExclusiveGroup(bool value) {
if (inMutuallyExclusiveGroup == value)
return;
_inMutuallyExclusiveGroup = value;
markNeedsSemanticsUpdate();
}
/// If non-null, sets the [SemanticsNode.label] semantic to the given value. /// If non-null, sets the [SemanticsNode.label] semantic to the given value.
/// ///
/// The reading direction is given by [textDirection]. /// The reading direction is given by [textDirection].
...@@ -3581,6 +3630,14 @@ class RenderSemanticsAnnotations extends RenderProxyBox { ...@@ -3581,6 +3630,14 @@ class RenderSemanticsAnnotations extends RenderProxyBox {
config.isSelected = selected; config.isSelected = selected;
if (button != null) if (button != null)
config.isButton = button; config.isButton = button;
if (header != null)
config.isHeader = header;
if (textField != null)
config.isTextField = textField;
if (focused != null)
config.isFocused = focused;
if (inMutuallyExclusiveGroup != null)
config.isInMutuallyExclusiveGroup = inMutuallyExclusiveGroup;
if (label != null) if (label != null)
config.label = label; config.label = label;
if (value != null) if (value != null)
......
...@@ -315,6 +315,10 @@ class SemanticsProperties extends DiagnosticableTree { ...@@ -315,6 +315,10 @@ class SemanticsProperties extends DiagnosticableTree {
this.checked, this.checked,
this.selected, this.selected,
this.button, this.button,
this.header,
this.textField,
this.focused,
this.inMutuallyExclusiveGroup,
this.label, this.label,
this.value, this.value,
this.increasedValue, this.increasedValue,
...@@ -366,6 +370,35 @@ class SemanticsProperties extends DiagnosticableTree { ...@@ -366,6 +370,35 @@ class SemanticsProperties extends DiagnosticableTree {
/// is focused. /// is focused.
final bool button; final bool button;
/// If non-null, indicates that this subtree represents a header.
///
/// A header divides into sections. For example, an address book application
/// might define headers A, B, C, etc. to divide the list of alphabetically
/// sorted contacts into sections.
final bool header;
/// If non-null, indicates that this subtree represents a text field.
///
/// TalkBack/VoiceOver provide special affordances to enter text into a
/// text field.
final bool textField;
/// If non-null, whether the node currently holds input focus.
///
/// At most one node in the tree should hold input focus at any point in time.
///
/// Input focus (indicates that the node will receive keyboard events) is not
/// to be confused with accessibility focus. Accessibility focus is the
/// green/black rectangular that TalkBack/VoiceOver on the screen and is
/// separate from input focus.
final bool focused;
/// If non-null, whether a semantic node is in a mutually exclusive group.
///
/// For example, a radio button is in a mutually exclusive group because only
/// one radio button in that group can be marked as [checked].
final bool inMutuallyExclusiveGroup;
/// Provides a textual description of the widget. /// Provides a textual description of the widget.
/// ///
/// If a label is provided, there must either by an ambient [Directionality] /// If a label is provided, there must either by an ambient [Directionality]
...@@ -2365,6 +2398,12 @@ class SemanticsConfiguration { ...@@ -2365,6 +2398,12 @@ class SemanticsConfiguration {
_setFlag(SemanticsFlag.isButton, value); _setFlag(SemanticsFlag.isButton, value);
} }
/// Whether the owning [RenderObject] is a header (true) or not (false).
bool get isHeader => _hasFlag(SemanticsFlag.isHeader);
set isHeader(bool value) {
_setFlag(SemanticsFlag.isHeader, value);
}
/// Whether the owning [RenderObject] is a text field. /// Whether the owning [RenderObject] is a text field.
bool get isTextField => _hasFlag(SemanticsFlag.isTextField); bool get isTextField => _hasFlag(SemanticsFlag.isTextField);
set isTextField(bool value) { set isTextField(bool value) {
......
...@@ -4847,6 +4847,10 @@ class Semantics extends SingleChildRenderObjectWidget { ...@@ -4847,6 +4847,10 @@ class Semantics extends SingleChildRenderObjectWidget {
bool checked, bool checked,
bool selected, bool selected,
bool button, bool button,
bool header,
bool textField,
bool focused,
bool inMutuallyExclusiveGroup,
String label, String label,
String value, String value,
String increasedValue, String increasedValue,
...@@ -4881,6 +4885,10 @@ class Semantics extends SingleChildRenderObjectWidget { ...@@ -4881,6 +4885,10 @@ class Semantics extends SingleChildRenderObjectWidget {
checked: checked, checked: checked,
selected: selected, selected: selected,
button: button, button: button,
header: header,
textField: textField,
focused: focused,
inMutuallyExclusiveGroup: inMutuallyExclusiveGroup,
label: label, label: label,
value: value, value: value,
increasedValue: increasedValue, increasedValue: increasedValue,
...@@ -4960,6 +4968,10 @@ class Semantics extends SingleChildRenderObjectWidget { ...@@ -4960,6 +4968,10 @@ class Semantics extends SingleChildRenderObjectWidget {
checked: properties.checked, checked: properties.checked,
selected: properties.selected, selected: properties.selected,
button: properties.button, button: properties.button,
header: properties.header,
textField: properties.textField,
focused: properties.focused,
inMutuallyExclusiveGroup: properties.inMutuallyExclusiveGroup,
label: properties.label, label: properties.label,
value: properties.value, value: properties.value,
increasedValue: properties.increasedValue, increasedValue: properties.increasedValue,
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:async'; import 'dart:async';
import 'dart:ui';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
...@@ -397,6 +398,52 @@ void _defineTests() { ...@@ -397,6 +398,52 @@ void _defineTests() {
semantics.dispose(); semantics.dispose();
}); });
testWidgets('Supports all flags', (WidgetTester tester) async {
final SemanticsTester semantics = new SemanticsTester(tester);
await tester.pumpWidget(new CustomPaint(
painter: new _PainterWithSemantics(
semantics: new CustomPainterSemantics(
key: const ValueKey<int>(1),
rect: new Rect.fromLTRB(1.0, 2.0, 3.0, 4.0),
properties: const SemanticsProperties(
enabled: true,
checked: true,
selected: true,
button: true,
textField: true,
focused: true,
inMutuallyExclusiveGroup: true,
header: true,
),
),
),
));
const int expectedId = 2;
final TestSemantics expectedSemantics = new TestSemantics.root(
children: <TestSemantics>[
new TestSemantics.rootChild(
id: 1,
previousNodeId: -1,
nextNodeId: expectedId,
children: <TestSemantics>[
new TestSemantics.rootChild(
id: expectedId,
rect: TestSemantics.fullScreen,
flags: SemanticsFlag.values.values.toList(),
previousNodeId: 1,
nextNodeId: -1,
),
]
),
],
);
expect(semantics, hasSemantics(expectedSemantics, ignoreRect: true, ignoreTransform: true));
semantics.dispose();
});
group('diffing', () { group('diffing', () {
testWidgets('complains about duplicate keys', (WidgetTester tester) async { testWidgets('complains about duplicate keys', (WidgetTester tester) async {
final SemanticsTester semanticsTester = new SemanticsTester(tester); final SemanticsTester semanticsTester = new SemanticsTester(tester);
......
...@@ -449,6 +449,39 @@ void main() { ...@@ -449,6 +449,39 @@ void main() {
semantics.dispose(); semantics.dispose();
}); });
testWidgets('Semantics widget supports all flags', (WidgetTester tester) async {
final SemanticsTester semantics = new SemanticsTester(tester);
await tester.pumpWidget(
new Semantics(
container: true,
// flags
enabled: true,
checked: true,
selected: true,
button: true,
textField: true,
focused: true,
inMutuallyExclusiveGroup: true,
header: true,
)
);
final TestSemantics expectedSemantics = new TestSemantics.root(
children: <TestSemantics>[
new TestSemantics.rootChild(
rect: TestSemantics.fullScreen,
flags: SemanticsFlag.values.values.toList(),
previousNodeId: -1,
nextNodeId: -1,
),
],
);
expect(semantics, hasSemantics(expectedSemantics, ignoreId: true));
semantics.dispose();
});
testWidgets('Actions can be replaced without triggering semantics update', (WidgetTester tester) async { testWidgets('Actions can be replaced without triggering semantics update', (WidgetTester tester) async {
final SemanticsTester semantics = new SemanticsTester(tester); final SemanticsTester semantics = new SemanticsTester(tester);
int semanticsUpdateCount = 0; int semanticsUpdateCount = 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment