Skip to content

Commit

Permalink
Fix: add Android accessibility bounds offset when FlutterView's locat…
Browse files Browse the repository at this point in the history
…ion is not left top corner (flutter#25670)
  • Loading branch information
eggfly authored Apr 20, 2021
1 parent 95003af commit 3393072
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 1 deletion.
17 changes: 16 additions & 1 deletion shell/platform/android/io/flutter/view/AccessibilityBridge.java
Original file line number Diff line number Diff line change
Expand Up @@ -693,7 +693,8 @@ public AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualViewId) {
} else {
result.setBoundsInParent(bounds);
}
result.setBoundsInScreen(bounds);
final Rect boundsInScreen = getBoundsInScreen(bounds);
result.setBoundsInScreen(boundsInScreen);
result.setVisibleToUser(true);
result.setEnabled(
!semanticsNode.hasFlag(Flag.HAS_ENABLED_STATE) || semanticsNode.hasFlag(Flag.IS_ENABLED));
Expand Down Expand Up @@ -869,6 +870,20 @@ && shouldSetCollectionInfo(semanticsNode)) {
return result;
}

/**
* Get the bounds in screen with root FlutterView's offset.
*
* @param bounds the bounds in FlutterView
* @return the bounds with offset
*/
private Rect getBoundsInScreen(Rect bounds) {
Rect boundsInScreen = new Rect(bounds);
int[] locationOnScreen = new int[2];
rootAccessibilityView.getLocationOnScreen(locationOnScreen);
boundsInScreen.offset(locationOnScreen[0], locationOnScreen[1]);
return boundsInScreen;
}

/**
* Instructs the view represented by {@code virtualViewId} to carry out the desired {@code
* accessibilityAction}, perhaps configured by additional {@code arguments}.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
Expand Down Expand Up @@ -76,6 +77,41 @@ public void itDescribesTextFieldsWithText() {
assertEquals(nodeInfo.getText(), "Hello, World");
}

@Test
public void itTakesGlobalCoordinatesOfFlutterViewIntoAccount() {
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);
final int position = 88;
// The getBoundsInScreen() in createAccessibilityNodeInfo() needs View.getLocationOnScreen()
doAnswer(
invocation -> {
int[] outLocation = (int[]) invocation.getArguments()[0];
outLocation[0] = position;
outLocation[1] = position;
return null;
})
.when(mockRootView)
.getLocationOnScreen(any(int[].class));

when(context.getPackageName()).thenReturn("test");
AccessibilityBridge accessibilityBridge =
setUpBridge(mockRootView, mockManager, mockViewEmbedder);

TestSemanticsNode testSemanticsNode = new TestSemanticsNode();
TestSemanticsUpdate testSemanticsUpdate = testSemanticsNode.toUpdate();

accessibilityBridge.updateSemantics(testSemanticsUpdate.buffer, testSemanticsUpdate.strings);
AccessibilityNodeInfo nodeInfo = accessibilityBridge.createAccessibilityNodeInfo(0);

Rect outBoundsInScreen = new Rect();
nodeInfo.getBoundsInScreen(outBoundsInScreen);
assertEquals(position, outBoundsInScreen.left);
assertEquals(position, outBoundsInScreen.top);
}

@Test
public void itDoesNotContainADescriptionIfScopesRoute() {
AccessibilityBridge accessibilityBridge = setUpBridge();
Expand Down

0 comments on commit 3393072

Please sign in to comment.