diff --git a/lib/ui/semantics.dart b/lib/ui/semantics.dart index 398dff2aca0a1afbd88a0f9a5ddb33f9826d634b..fcddf844d88914189026a8609569c446df6ba0c2 100644 --- a/lib/ui/semantics.dart +++ b/lib/ui/semantics.dart @@ -145,6 +145,7 @@ class SemanticsFlags { static const int _kIsButtonIndex = 1 << 3; static const int _kIsTextFieldIndex = 1 << 4; static const int _kIsFocusedIndex = 1 << 5; + static const int _kIsDisabledIndex = 1 << 6; const SemanticsFlags._(this.index); @@ -193,6 +194,16 @@ class SemanticsFlags { /// The focused element is usually the current receiver of keyboard inputs. static const SemanticsFlags isFocused = const SemanticsFlags._(_kIsFocusedIndex); + /// Whether the semantic node is currently disabled. + /// + /// A disabled element does not respond to user interaction. For example, a + /// button that currently does not respond to user interaction should be + /// marked as disabled. + /// + /// Elements, that never respond to user interactions (e.g. static text) + /// should not be marked as disabled. + static const SemanticsFlags isDisabled = const SemanticsFlags._(_kIsDisabledIndex); + /// The possible semantics flags. /// /// The map's key is the [index] of the flag and the value is the flag itself. @@ -203,6 +214,7 @@ class SemanticsFlags { _kIsButtonIndex: isButton, _kIsTextFieldIndex: isTextField, _kIsFocusedIndex: isFocused, + _kIsDisabledIndex: isDisabled, }; @override @@ -220,6 +232,8 @@ class SemanticsFlags { return 'SemanticsFlags.isTextField'; case _kIsFocusedIndex: return 'SemanticsFlags.isFocused'; + case _kIsDisabledIndex: + return 'SemanticsFlags.isDisabled'; } return null; } diff --git a/lib/ui/semantics/semantics_node.h b/lib/ui/semantics/semantics_node.h index 4335babb840a7b6b3118d02ad1ca323715df4bca..5e09248e603e4ebf55f20c7d41838f8b528bc9e4 100644 --- a/lib/ui/semantics/semantics_node.h +++ b/lib/ui/semantics/semantics_node.h @@ -41,6 +41,7 @@ enum class SemanticsFlags : int32_t { kIsButton = 1 << 3, kIsTextField = 1 << 4, kIsFocused = 1 << 5, + kIsDisabled = 1 << 6, }; struct SemanticsNode { diff --git a/shell/platform/android/io/flutter/view/AccessibilityBridge.java b/shell/platform/android/io/flutter/view/AccessibilityBridge.java index 958aa6fb5d5d6006b45189f4ede27accf4076343..c85f45d38162be7651cdea76c8ba2fed618b9541 100644 --- a/shell/platform/android/io/flutter/view/AccessibilityBridge.java +++ b/shell/platform/android/io/flutter/view/AccessibilityBridge.java @@ -65,7 +65,8 @@ class AccessibilityBridge extends AccessibilityNodeProvider implements BasicMess IS_SELECTED(1 << 2), IS_BUTTON(1 << 3), IS_TEXT_FIELD(1 << 4), - IS_FOCUSED(1 << 5); + IS_FOCUSED(1 << 5), + IS_DISABLED(1 << 6); Flag(int value) { this.value = value; @@ -157,7 +158,7 @@ class AccessibilityBridge extends AccessibilityNodeProvider implements BasicMess } result.setBoundsInScreen(bounds); result.setVisibleToUser(true); - result.setEnabled(true); // TODO(ianh): Expose disabled subtrees + result.setEnabled(!object.hasFlag(Flag.IS_DISABLED)); if (object.hasAction(Action.TAP)) { result.addAction(AccessibilityNodeInfo.ACTION_CLICK); diff --git a/shell/platform/darwin/ios/framework/Source/accessibility_bridge.mm b/shell/platform/darwin/ios/framework/Source/accessibility_bridge.mm index b72d57bd8fa4a52031c43440d8ed9ec212410b5e..1c531aa52cf7138c5b6c66c4a7636078edbebab5 100644 --- a/shell/platform/darwin/ios/framework/Source/accessibility_bridge.mm +++ b/shell/platform/darwin/ios/framework/Source/accessibility_bridge.mm @@ -194,6 +194,9 @@ bool GeometryComparator(SemanticsObject* a, SemanticsObject* b) { if (_node.HasFlag(blink::SemanticsFlags::kIsButton)) { traits |= UIAccessibilityTraitButton; } + if (_node.HasFlag(blink::SemanticsFlags::kIsDisabled)) { + traits |= UIAccessibilityTraitNotEnabled; + } return traits; }