diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterSurfaceView.java b/shell/platform/android/io/flutter/embedding/android/FlutterSurfaceView.java index 264e2b41cc7a2..1d6bccc77a7ea 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterSurfaceView.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterSurfaceView.java @@ -6,6 +6,7 @@ import android.content.Context; import android.graphics.PixelFormat; +import android.graphics.Region; import android.util.AttributeSet; import android.view.SurfaceHolder; import android.view.SurfaceView; @@ -135,6 +136,28 @@ private void init() { setAlpha(0.0f); } + // This is a work around for TalkBack. + // If Android decides that our layer is transparent because, e.g. the status- + // bar is transparent, TalkBack highlighting stops working. + // Explicitly telling Android this part of the region is not actually + // transparent makes TalkBack work again. + // See https://github.com/flutter/flutter/issues/73413 for context. + @Override + public boolean gatherTransparentRegion(Region region) { + if (getAlpha() < 1.0f) { + return false; + } + final int[] location = new int[2]; + getLocationInWindow(location); + region.op( + location[0], + location[1], + location[0] + getRight() - getLeft(), + location[1] + getBottom() - getTop(), + Region.Op.DIFFERENCE); + return true; + } + @Nullable @Override public FlutterRenderer getAttachedRenderer() { diff --git a/shell/platform/android/test/io/flutter/embedding/android/FlutterViewTest.java b/shell/platform/android/test/io/flutter/embedding/android/FlutterViewTest.java index 7c48e24134fbe..5f7657b5df404 100644 --- a/shell/platform/android/test/io/flutter/embedding/android/FlutterViewTest.java +++ b/shell/platform/android/test/io/flutter/embedding/android/FlutterViewTest.java @@ -19,6 +19,7 @@ import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.Insets; +import android.graphics.Region; import android.media.Image; import android.media.Image.Plane; import android.media.ImageReader; @@ -795,6 +796,20 @@ public void flutterImageView_onDrawClosesAllImages() { verify(mockImage, times(2)).close(); } + @Test + public void flutterSurfaceView_GathersTransparentRegion() { + final Region mockRegion = mock(Region.class); + final FlutterSurfaceView surfaceView = new FlutterSurfaceView(RuntimeEnvironment.application); + + surfaceView.setAlpha(0.0f); + assertFalse(surfaceView.gatherTransparentRegion(mockRegion)); + verify(mockRegion, times(0)).op(anyInt(), anyInt(), anyInt(), anyInt(), any()); + + surfaceView.setAlpha(1.0f); + assertTrue(surfaceView.gatherTransparentRegion(mockRegion)); + verify(mockRegion, times(1)).op(0, 0, 0, 0, Region.Op.DIFFERENCE); + } + /* * A custom shadow that reports fullscreen flag for system UI visibility */