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

Support SemanticsFlag for Header (#15255)

parent 96ce9d64
......@@ -152,7 +152,10 @@ class GalleryHomeState extends State<GalleryHome> with SingleTickerProviderState
child: new SafeArea(
top: false,
bottom: false,
child: new Text(galleryItem.category, style: headerStyle),
child: new Semantics(
header: true,
child: new Text(galleryItem.category, style: headerStyle),
),
),
),
)
......
......@@ -817,6 +817,21 @@ class RenderCustomPaint extends RenderProxyBox {
if (properties.button != null) {
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) {
config.label = properties.label;
}
......
......@@ -3015,6 +3015,10 @@ class RenderSemanticsAnnotations extends RenderProxyBox {
bool checked,
bool selected,
bool button,
bool header,
bool textField,
bool focused,
bool inMutuallyExclusiveGroup,
String label,
String value,
String increasedValue,
......@@ -3045,6 +3049,10 @@ class RenderSemanticsAnnotations extends RenderProxyBox {
_checked = checked,
_selected = selected,
_button = button,
_header = header,
_textField = textField,
_focused = focused,
_inMutuallyExclusiveGroup = inMutuallyExclusiveGroup,
_label = label,
_value = value,
_increasedValue = increasedValue,
......@@ -3152,6 +3160,47 @@ class RenderSemanticsAnnotations extends RenderProxyBox {
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.
///
/// The reading direction is given by [textDirection].
......@@ -3581,6 +3630,14 @@ class RenderSemanticsAnnotations extends RenderProxyBox {
config.isSelected = selected;
if (button != null)
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)
config.label = label;
if (value != null)
......
......@@ -315,6 +315,10 @@ class SemanticsProperties extends DiagnosticableTree {
this.checked,
this.selected,
this.button,
this.header,
this.textField,
this.focused,
this.inMutuallyExclusiveGroup,
this.label,
this.value,
this.increasedValue,
......@@ -366,6 +370,35 @@ class SemanticsProperties extends DiagnosticableTree {
/// is focused.
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.
///
/// If a label is provided, there must either by an ambient [Directionality]
......@@ -2365,6 +2398,12 @@ class SemanticsConfiguration {
_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.
bool get isTextField => _hasFlag(SemanticsFlag.isTextField);
set isTextField(bool value) {
......
......@@ -4847,6 +4847,10 @@ class Semantics extends SingleChildRenderObjectWidget {
bool checked,
bool selected,
bool button,
bool header,
bool textField,
bool focused,
bool inMutuallyExclusiveGroup,
String label,
String value,
String increasedValue,
......@@ -4881,6 +4885,10 @@ class Semantics extends SingleChildRenderObjectWidget {
checked: checked,
selected: selected,
button: button,
header: header,
textField: textField,
focused: focused,
inMutuallyExclusiveGroup: inMutuallyExclusiveGroup,
label: label,
value: value,
increasedValue: increasedValue,
......@@ -4960,6 +4968,10 @@ class Semantics extends SingleChildRenderObjectWidget {
checked: properties.checked,
selected: properties.selected,
button: properties.button,
header: properties.header,
textField: properties.textField,
focused: properties.focused,
inMutuallyExclusiveGroup: properties.inMutuallyExclusiveGroup,
label: properties.label,
value: properties.value,
increasedValue: properties.increasedValue,
......
......@@ -3,6 +3,7 @@
// found in the LICENSE file.
import 'dart:async';
import 'dart:ui';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/rendering.dart';
......@@ -397,6 +398,52 @@ void _defineTests() {
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', () {
testWidgets('complains about duplicate keys', (WidgetTester tester) async {
final SemanticsTester semanticsTester = new SemanticsTester(tester);
......
......@@ -449,6 +449,39 @@ void main() {
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 {
final SemanticsTester semantics = new SemanticsTester(tester);
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