mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
remove top padding when system UI in fullscreen mode (#17985)
This commit is contained in:
parent
893cb3731c
commit
45e6cfd1ff
@ -400,10 +400,11 @@ public class FlutterView extends FrameLayout {
|
||||
@SuppressLint({"InlinedApi", "NewApi"})
|
||||
@NonNull
|
||||
public final WindowInsets onApplyWindowInsets(@NonNull WindowInsets insets) {
|
||||
boolean statusBarHidden = (SYSTEM_UI_FLAG_FULLSCREEN & getWindowSystemUiVisibility()) != 0;
|
||||
WindowInsets newInsets = super.onApplyWindowInsets(insets);
|
||||
|
||||
// Status bar (top) and left/right system insets should partially obscure the content (padding).
|
||||
viewportMetrics.paddingTop = insets.getSystemWindowInsetTop();
|
||||
viewportMetrics.paddingTop = statusBarHidden ? 0 : insets.getSystemWindowInsetTop();
|
||||
viewportMetrics.paddingRight = insets.getSystemWindowInsetRight();
|
||||
viewportMetrics.paddingBottom = 0;
|
||||
viewportMetrics.paddingLeft = insets.getSystemWindowInsetLeft();
|
||||
|
||||
@ -8,9 +8,13 @@ import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowInsets;
|
||||
import io.flutter.embedding.engine.FlutterEngine;
|
||||
import io.flutter.embedding.engine.FlutterJNI;
|
||||
import io.flutter.embedding.engine.loader.FlutterLoader;
|
||||
@ -21,6 +25,7 @@ import java.util.concurrent.atomic.AtomicReference;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.Spy;
|
||||
@ -29,9 +34,16 @@ import org.mockito.stubbing.Answer;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.annotation.Implementation;
|
||||
import org.robolectric.annotation.Implements;
|
||||
|
||||
@Config(manifest = Config.NONE)
|
||||
// TODO(xster): we have 2 versions of robolectric Android shadows in
|
||||
// shell/platform/android/embedding_bundle/build.gradle. Remove the older
|
||||
// org.robolectric:android-all:4.1.2_r1-robolectric-r1 which doesn't have the right shadow
|
||||
// behaviors.
|
||||
@Config(manifest = Config.NONE, sdk = 27)
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@TargetApi(27)
|
||||
public class FlutterViewTest {
|
||||
@Mock FlutterJNI mockFlutterJni;
|
||||
@Mock FlutterLoader mockFlutterLoader;
|
||||
@ -188,4 +200,97 @@ public class FlutterViewTest {
|
||||
// Verify results.
|
||||
assertEquals(SettingsChannel.PlatformBrightness.dark, reportedBrightness.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Config(
|
||||
shadows = {
|
||||
FlutterViewTest.ShadowFullscreenView.class,
|
||||
FlutterViewTest.ShadowFullscreenViewGroup.class
|
||||
})
|
||||
public void setPaddingTopToZeroForFullscreenMode() {
|
||||
FlutterView flutterView = new FlutterView(RuntimeEnvironment.application);
|
||||
FlutterEngine flutterEngine =
|
||||
spy(new FlutterEngine(RuntimeEnvironment.application, mockFlutterLoader, mockFlutterJni));
|
||||
FlutterRenderer flutterRenderer = spy(new FlutterRenderer(mockFlutterJni));
|
||||
when(flutterEngine.getRenderer()).thenReturn(flutterRenderer);
|
||||
|
||||
// When we attach a new FlutterView to the engine without any system insets, the viewport
|
||||
// metrics
|
||||
// default to 0.
|
||||
flutterView.attachToFlutterEngine(flutterEngine);
|
||||
ArgumentCaptor<FlutterRenderer.ViewportMetrics> viewportMetricsCaptor =
|
||||
ArgumentCaptor.forClass(FlutterRenderer.ViewportMetrics.class);
|
||||
verify(flutterRenderer).setViewportMetrics(viewportMetricsCaptor.capture());
|
||||
assertEquals(0, viewportMetricsCaptor.getValue().paddingTop);
|
||||
|
||||
// Then we simulate the system applying a window inset.
|
||||
WindowInsets windowInsets = mock(WindowInsets.class);
|
||||
when(windowInsets.getSystemWindowInsetTop()).thenReturn(100);
|
||||
when(windowInsets.getSystemWindowInsetBottom()).thenReturn(100);
|
||||
when(windowInsets.getSystemWindowInsetLeft()).thenReturn(100);
|
||||
when(windowInsets.getSystemWindowInsetRight()).thenReturn(100);
|
||||
flutterView.onApplyWindowInsets(windowInsets);
|
||||
|
||||
// Verify.
|
||||
verify(flutterRenderer, times(2)).setViewportMetrics(viewportMetricsCaptor.capture());
|
||||
assertEquals(0, viewportMetricsCaptor.getValue().paddingTop);
|
||||
// Padding bottom is always 0.
|
||||
assertEquals(0, viewportMetricsCaptor.getValue().paddingBottom);
|
||||
assertEquals(100, viewportMetricsCaptor.getValue().paddingLeft);
|
||||
assertEquals(100, viewportMetricsCaptor.getValue().paddingRight);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void reportSystemInsetWhenNotFullscreen() {
|
||||
// Without custom shadows, the default system ui visibility flags is 0.
|
||||
FlutterView flutterView = new FlutterView(RuntimeEnvironment.application);
|
||||
assertEquals(0, flutterView.getSystemUiVisibility());
|
||||
|
||||
FlutterEngine flutterEngine =
|
||||
spy(new FlutterEngine(RuntimeEnvironment.application, mockFlutterLoader, mockFlutterJni));
|
||||
FlutterRenderer flutterRenderer = spy(new FlutterRenderer(mockFlutterJni));
|
||||
when(flutterEngine.getRenderer()).thenReturn(flutterRenderer);
|
||||
|
||||
// When we attach a new FlutterView to the engine without any system insets, the viewport
|
||||
// metrics
|
||||
// default to 0.
|
||||
flutterView.attachToFlutterEngine(flutterEngine);
|
||||
ArgumentCaptor<FlutterRenderer.ViewportMetrics> viewportMetricsCaptor =
|
||||
ArgumentCaptor.forClass(FlutterRenderer.ViewportMetrics.class);
|
||||
verify(flutterRenderer).setViewportMetrics(viewportMetricsCaptor.capture());
|
||||
assertEquals(0, viewportMetricsCaptor.getValue().paddingTop);
|
||||
|
||||
// Then we simulate the system applying a window inset.
|
||||
WindowInsets windowInsets = mock(WindowInsets.class);
|
||||
when(windowInsets.getSystemWindowInsetTop()).thenReturn(100);
|
||||
when(windowInsets.getSystemWindowInsetBottom()).thenReturn(100);
|
||||
when(windowInsets.getSystemWindowInsetLeft()).thenReturn(100);
|
||||
when(windowInsets.getSystemWindowInsetRight()).thenReturn(100);
|
||||
flutterView.onApplyWindowInsets(windowInsets);
|
||||
|
||||
// Verify.
|
||||
verify(flutterRenderer, times(2)).setViewportMetrics(viewportMetricsCaptor.capture());
|
||||
// Top padding is reported as-is.
|
||||
assertEquals(100, viewportMetricsCaptor.getValue().paddingTop);
|
||||
// Padding bottom is always 0.
|
||||
assertEquals(0, viewportMetricsCaptor.getValue().paddingBottom);
|
||||
assertEquals(100, viewportMetricsCaptor.getValue().paddingLeft);
|
||||
assertEquals(100, viewportMetricsCaptor.getValue().paddingRight);
|
||||
}
|
||||
|
||||
/*
|
||||
* A custom shadow that reports fullscreen flag for system UI visibility
|
||||
*/
|
||||
@Implements(View.class)
|
||||
public static class ShadowFullscreenView {
|
||||
@Implementation
|
||||
public int getWindowSystemUiVisibility() {
|
||||
return View.SYSTEM_UI_FLAG_FULLSCREEN;
|
||||
}
|
||||
}
|
||||
|
||||
// ViewGroup is the first shadow in the type hierarchy for FlutterView. Shadows need to mimic
|
||||
// production classes' view hierarchy.
|
||||
@Implements(ViewGroup.class)
|
||||
public static class ShadowFullscreenViewGroup extends ShadowFullscreenView {}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user