mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Updates accessible_navigation trigger in Android (flutter/engine#35478)
* Updates accessible_navigation trigger in Android * update doc comments * comment * addressing comment
This commit is contained in:
parent
c01ef41e9e
commit
1a38d2e54b
@ -257,6 +257,30 @@ public class AccessibilityBridge extends AccessibilityNodeProvider {
|
||||
|
||||
@Nullable private OnAccessibilityChangeListener onAccessibilityChangeListener;
|
||||
|
||||
// Whether the users are using assistive technologies to interact with the devices.
|
||||
//
|
||||
// The getter returns true when at least one of the assistive technologies is running:
|
||||
// TalkBack, SwitchAccess, or VoiceAccess.
|
||||
@VisibleForTesting
|
||||
public boolean getAccessibleNavigation() {
|
||||
return accessibleNavigation;
|
||||
}
|
||||
|
||||
private boolean accessibleNavigation = false;
|
||||
|
||||
private void setAccessibleNavigation(boolean value) {
|
||||
if (accessibleNavigation == value) {
|
||||
return;
|
||||
}
|
||||
accessibleNavigation = value;
|
||||
if (accessibleNavigation) {
|
||||
accessibilityFeatureFlags |= AccessibilityFeature.ACCESSIBLE_NAVIGATION.value;
|
||||
} else {
|
||||
accessibilityFeatureFlags &= ~AccessibilityFeature.ACCESSIBLE_NAVIGATION.value;
|
||||
}
|
||||
sendLatestAccessibilityFlagsToFlutter();
|
||||
}
|
||||
|
||||
// Set to true after {@code release} has been invoked.
|
||||
private boolean isReleased = false;
|
||||
|
||||
@ -331,6 +355,7 @@ public class AccessibilityBridge extends AccessibilityNodeProvider {
|
||||
accessibilityChannel.setAccessibilityMessageHandler(accessibilityMessageHandler);
|
||||
accessibilityChannel.onAndroidAccessibilityEnabled();
|
||||
} else {
|
||||
setAccessibleNavigation(false);
|
||||
accessibilityChannel.setAccessibilityMessageHandler(null);
|
||||
accessibilityChannel.onAndroidAccessibilityDisabled();
|
||||
}
|
||||
@ -409,7 +434,6 @@ public class AccessibilityBridge extends AccessibilityNodeProvider {
|
||||
this.contentResolver = contentResolver;
|
||||
this.accessibilityViewEmbedder = accessibilityViewEmbedder;
|
||||
this.platformViewsAccessibilityDelegate = platformViewsAccessibilityDelegate;
|
||||
|
||||
// Tell Flutter whether accessibility is initially active or not. Then register a listener
|
||||
// to be notified of changes in the future.
|
||||
accessibilityStateChangeListener.onAccessibilityStateChanged(accessibilityManager.isEnabled());
|
||||
@ -425,13 +449,10 @@ public class AccessibilityBridge extends AccessibilityNodeProvider {
|
||||
if (isReleased) {
|
||||
return;
|
||||
}
|
||||
if (isTouchExplorationEnabled) {
|
||||
accessibilityFeatureFlags |= AccessibilityFeature.ACCESSIBLE_NAVIGATION.value;
|
||||
} else {
|
||||
if (!isTouchExplorationEnabled) {
|
||||
setAccessibleNavigation(false);
|
||||
onTouchExplorationExit();
|
||||
accessibilityFeatureFlags &= ~AccessibilityFeature.ACCESSIBLE_NAVIGATION.value;
|
||||
}
|
||||
sendLatestAccessibilityFlagsToFlutter();
|
||||
|
||||
if (onAccessibilityChangeListener != null) {
|
||||
onAccessibilityChangeListener.onAccessibilityChanged(
|
||||
@ -551,6 +572,7 @@ public class AccessibilityBridge extends AccessibilityNodeProvider {
|
||||
// Suppressing Lint warning for new API, as we are version guarding all calls to newer APIs
|
||||
@SuppressLint("NewApi")
|
||||
public AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualViewId) {
|
||||
setAccessibleNavigation(true);
|
||||
if (virtualViewId >= MIN_ENGINE_GENERATED_NODE_ID) {
|
||||
// The node is in the engine generated range, and is provided by the accessibility view
|
||||
// embedder.
|
||||
|
||||
@ -124,6 +124,44 @@ public class AccessibilityBridgeTest {
|
||||
assertEquals(position, outBoundsInScreen.top);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void itSetsAccessibleNavigation() {
|
||||
AccessibilityChannel mockChannel = mock(AccessibilityChannel.class);
|
||||
AccessibilityViewEmbedder mockViewEmbedder = mock(AccessibilityViewEmbedder.class);
|
||||
AccessibilityManager mockManager = mock(AccessibilityManager.class);
|
||||
View mockRootView = mock(View.class);
|
||||
Context context = mock(Context.class);
|
||||
when(mockRootView.getContext()).thenReturn(context);
|
||||
when(context.getPackageName()).thenReturn("test");
|
||||
when(mockManager.isTouchExplorationEnabled()).thenReturn(false);
|
||||
AccessibilityBridge accessibilityBridge =
|
||||
setUpBridge(
|
||||
/*rootAccessibilityView=*/ mockRootView,
|
||||
/*accessibilityChannel=*/ mockChannel,
|
||||
/*accessibilityManager=*/ mockManager,
|
||||
/*contentResolver=*/ null,
|
||||
/*accessibilityViewEmbedder=*/ mockViewEmbedder,
|
||||
/*platformViewsAccessibilityDelegate=*/ null);
|
||||
ArgumentCaptor<AccessibilityManager.TouchExplorationStateChangeListener> listenerCaptor =
|
||||
ArgumentCaptor.forClass(AccessibilityManager.TouchExplorationStateChangeListener.class);
|
||||
verify(mockManager).addTouchExplorationStateChangeListener(listenerCaptor.capture());
|
||||
|
||||
assertEquals(accessibilityBridge.getAccessibleNavigation(), false);
|
||||
verify(mockChannel).setAccessibilityFeatures(0);
|
||||
reset(mockChannel);
|
||||
|
||||
// Simulate assistive technology accessing accessibility tree.
|
||||
accessibilityBridge.createAccessibilityNodeInfo(0);
|
||||
verify(mockChannel).setAccessibilityFeatures(1);
|
||||
assertEquals(accessibilityBridge.getAccessibleNavigation(), true);
|
||||
|
||||
// Simulate turning off TalkBack.
|
||||
reset(mockChannel);
|
||||
listenerCaptor.getValue().onTouchExplorationStateChanged(false);
|
||||
verify(mockChannel).setAccessibilityFeatures(0);
|
||||
assertEquals(accessibilityBridge.getAccessibleNavigation(), false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void itDoesNotContainADescriptionIfScopesRoute() {
|
||||
AccessibilityBridge accessibilityBridge = setUpBridge();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user