Introduce read only text field semantics (flutter/engine#9281)
This commit is contained in:
@@ -288,6 +288,7 @@ class SemanticsFlag {
|
||||
static const int _kHasToggledStateIndex = 1 << 16;
|
||||
static const int _kIsToggledIndex = 1 << 17;
|
||||
static const int _kHasImplicitScrollingIndex = 1 << 18;
|
||||
static const int _kIsReadOnlyIndex = 1 << 20;
|
||||
|
||||
const SemanticsFlag._(this.index);
|
||||
|
||||
@@ -341,6 +342,11 @@ class SemanticsFlag {
|
||||
/// affordances.
|
||||
static const SemanticsFlag isTextField = SemanticsFlag._(_kIsTextFieldIndex);
|
||||
|
||||
/// Whether the semantic node is read only.
|
||||
///
|
||||
/// Only applicable when [isTextField] is true.
|
||||
static const SemanticsFlag isReadOnly = SemanticsFlag._(_kIsReadOnlyIndex);
|
||||
|
||||
/// Whether the semantic node currently holds the user's focus.
|
||||
///
|
||||
/// The focused element is usually the current receiver of keyboard inputs.
|
||||
@@ -506,6 +512,7 @@ class SemanticsFlag {
|
||||
_kHasToggledStateIndex: hasToggledState,
|
||||
_kIsToggledIndex: isToggled,
|
||||
_kHasImplicitScrollingIndex: hasImplicitScrolling,
|
||||
_kIsReadOnlyIndex: isReadOnly,
|
||||
};
|
||||
|
||||
@override
|
||||
@@ -549,6 +556,8 @@ class SemanticsFlag {
|
||||
return 'SemanticsFlag.isToggled';
|
||||
case _kHasImplicitScrollingIndex:
|
||||
return 'SemanticsFlag.hasImplicitScrolling';
|
||||
case _kIsReadOnlyIndex:
|
||||
return 'SemanticsFlag.isReadOnly';
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -69,6 +69,7 @@ enum class SemanticsFlags : int32_t {
|
||||
kHasToggledState = 1 << 16,
|
||||
kIsToggled = 1 << 17,
|
||||
kHasImplicitScrolling = 1 << 18,
|
||||
kIsReadOnly = 1 << 20,
|
||||
};
|
||||
|
||||
const int kScrollableSemanticsFlags =
|
||||
|
||||
@@ -529,9 +529,11 @@ public class AccessibilityBridge extends AccessibilityNodeProvider {
|
||||
|
||||
if (semanticsNode.hasFlag(Flag.IS_TEXT_FIELD)) {
|
||||
result.setPassword(semanticsNode.hasFlag(Flag.IS_OBSCURED));
|
||||
result.setClassName("android.widget.EditText");
|
||||
if (!semanticsNode.hasFlag(Flag.IS_READ_ONLY)) {
|
||||
result.setClassName("android.widget.EditText");
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
||||
result.setEditable(true);
|
||||
result.setEditable(!semanticsNode.hasFlag(Flag.IS_READ_ONLY));
|
||||
if (semanticsNode.textSelectionBase != -1 && semanticsNode.textSelectionExtent != -1) {
|
||||
result.setTextSelection(semanticsNode.textSelectionBase, semanticsNode.textSelectionExtent);
|
||||
}
|
||||
@@ -1611,7 +1613,8 @@ public class AccessibilityBridge extends AccessibilityNodeProvider {
|
||||
IS_LIVE_REGION(1 << 15),
|
||||
HAS_TOGGLED_STATE(1 << 16),
|
||||
IS_TOGGLED(1 << 17),
|
||||
HAS_IMPLICIT_SCROLLING(1 << 18);
|
||||
HAS_IMPLICIT_SCROLLING(1 << 18),
|
||||
IS_READ_ONLY(1 << 20);
|
||||
|
||||
final int value;
|
||||
|
||||
|
||||
@@ -713,7 +713,8 @@ SemanticsObject* AccessibilityBridge::GetOrCreateObject(int32_t uid,
|
||||
if (!object) {
|
||||
// New node case: simply create a new SemanticsObject.
|
||||
flutter::SemanticsNode node = updates[uid];
|
||||
if (node.HasFlag(flutter::SemanticsFlags::kIsTextField)) {
|
||||
if (node.HasFlag(flutter::SemanticsFlags::kIsTextField) &&
|
||||
!node.HasFlag(flutter::SemanticsFlags::kIsReadOnly)) {
|
||||
// Text fields are backed by objects that implement UITextInput.
|
||||
object = [[[TextInputSemanticsObject alloc] initWithBridge:GetWeakPtr() uid:uid] autorelease];
|
||||
} else {
|
||||
@@ -729,13 +730,16 @@ SemanticsObject* AccessibilityBridge::GetOrCreateObject(int32_t uid,
|
||||
flutter::SemanticsNode node = nodeEntry->second;
|
||||
BOOL isTextField = node.HasFlag(flutter::SemanticsFlags::kIsTextField);
|
||||
BOOL wasTextField = object.node.HasFlag(flutter::SemanticsFlags::kIsTextField);
|
||||
if (wasTextField != isTextField) {
|
||||
BOOL isReadOnly = node.HasFlag(flutter::SemanticsFlags::kIsReadOnly);
|
||||
BOOL wasReadOnly = object.node.HasFlag(flutter::SemanticsFlags::kIsReadOnly);
|
||||
if (wasTextField != isTextField || isReadOnly != wasReadOnly) {
|
||||
// The node changed its type from text field to something else, or vice versa. In this
|
||||
// case, we cannot reuse the existing SemanticsObject implementation. Instead, we replace
|
||||
// it with a new instance.
|
||||
NSUInteger positionInChildlist = [object.parent.children indexOfObject:object];
|
||||
SemanticsObject* parent = object.parent;
|
||||
[objects_ removeObjectForKey:@(node.id)];
|
||||
if (isTextField) {
|
||||
if (isTextField && !isReadOnly) {
|
||||
// Text fields are backed by objects that implement UITextInput.
|
||||
object = [[[TextInputSemanticsObject alloc] initWithBridge:GetWeakPtr()
|
||||
uid:uid] autorelease];
|
||||
@@ -743,6 +747,7 @@ SemanticsObject* AccessibilityBridge::GetOrCreateObject(int32_t uid,
|
||||
object = [[[FlutterSemanticsObject alloc] initWithBridge:GetWeakPtr()
|
||||
uid:uid] autorelease];
|
||||
}
|
||||
object.parent = parent;
|
||||
[object.parent.children replaceObjectAtIndex:positionInChildlist withObject:object];
|
||||
objects_.get()[@(node.id)] = object;
|
||||
}
|
||||
|
||||
@@ -153,6 +153,10 @@ typedef enum {
|
||||
// |PageView| widget does not have implicit scrolling, so that users don't
|
||||
// navigate to the next page when reaching the end of the current one.
|
||||
kFlutterSemanticsFlagHasImplicitScrolling = 1 << 18,
|
||||
// Whether the semantic node is read only.
|
||||
//
|
||||
// Only applicable when kFlutterSemanticsFlagIsTextField flag is on.
|
||||
kFlutterSemanticsFlagIsReadOnly = 1 << 20,
|
||||
} FlutterSemanticsFlag;
|
||||
|
||||
typedef enum {
|
||||
|
||||
Reference in New Issue
Block a user