diff --git a/lib/ui/semantics.dart b/lib/ui/semantics.dart index 7d5f537c2..ed289c368 100644 --- a/lib/ui/semantics.dart +++ b/lib/ui/semantics.dart @@ -124,6 +124,8 @@ class SemanticsFlags { static const int _kIsCheckedIndex = 1 << 1; static const int _kIsSelectedIndex = 1 << 2; static const int _kIsButtonIndex = 1 << 3; + static const int _kIsTextFieldIndex = 1 << 4; + static const int _kIsFocusedIndex = 1 << 5; const SemanticsFlags._(this.index); @@ -161,6 +163,17 @@ class SemanticsFlags { /// a button. static const SemanticsFlags isButton = const SemanticsFlags._(_kIsButtonIndex); + /// Whether the semantic node represents a text field. + /// + /// Text fields are announced as such and allow text input via accessibility + /// affordances. + static const SemanticsFlags isTextField = const SemanticsFlags._(_kIsTextFieldIndex); + + /// Whether the semantic node currently holds the user's focus. + /// + /// The focused element is usually the current receiver of keyboard inputs. + static const SemanticsFlags isFocused = const SemanticsFlags._(_kIsFocusedIndex); + /// The possible semantics flags. /// /// The map's key is the [index] of the flag and the value is the flag itself. @@ -168,7 +181,9 @@ class SemanticsFlags { _kHasCheckedStateIndex: hasCheckedState, _kIsCheckedIndex: isChecked, _kIsSelectedIndex: isSelected, - _kIsButtonIndex: isButton + _kIsButtonIndex: isButton, + _kIsTextFieldIndex: isTextField, + _kIsFocusedIndex: isFocused, }; @override @@ -182,6 +197,10 @@ class SemanticsFlags { return 'SemanticsFlags.isSelected'; case _kIsButtonIndex: return 'SemanticsFlags.isButton'; + case _kIsTextFieldIndex: + return 'SemanticsFlags.isTextField'; + case _kIsFocusedIndex: + return 'SemanticsFlags.isFocused'; } return null; } diff --git a/shell/platform/android/io/flutter/view/AccessibilityBridge.java b/shell/platform/android/io/flutter/view/AccessibilityBridge.java index 871b39b65..4cfa126af 100644 --- a/shell/platform/android/io/flutter/view/AccessibilityBridge.java +++ b/shell/platform/android/io/flutter/view/AccessibilityBridge.java @@ -57,6 +57,8 @@ class AccessibilityBridge extends AccessibilityNodeProvider implements BasicMess private static final int SEMANTICS_FLAG_IS_CHECKED = 1 << 1; private static final int SEMANTICS_FLAG_IS_SELECTED = 1 << 2; private static final int SEMANTICS_FLAG_IS_BUTTON = 1 << 3; + private static final int SEMANTICS_FLAG_IS_TEXT_FIELD = 1 << 4; + private static final int SEMANTICS_FLAG_IS_FOCUSED = 1 << 5; AccessibilityBridge(FlutterView owner) { assert owner != null; @@ -95,9 +97,14 @@ class AccessibilityBridge extends AccessibilityNodeProvider implements BasicMess result.setClassName("Flutter"); // TODO(goderbauer): Set proper class names result.setSource(mOwner, virtualViewId); result.setFocusable(object.isFocusable()); + result.setFocused((object.flags & SEMANTICS_FLAG_IS_FOCUSED) != 0); + if (mFocusedObject != null) result.setAccessibilityFocused(mFocusedObject.id == virtualViewId); + if ((object.flags & SEMANTICS_FLAG_IS_TEXT_FIELD) != 0) + result.setClassName("android.widget.EditText"); + if (object.parent != null) { assert object.id > 0; result.setParent(mOwner, object.parent.id);