在应用中全屏显示内容

试用 Compose 方式
Jetpack Compose 是推荐用于 Android 的界面工具包。了解如何在 Compose 中使用全屏显示功能。

您可以在系统栏后面绘制,让应用全屏显示(使用屏幕的整个宽度和高度)。系统栏是状态栏和导航栏。

如需实现全屏布局,您的应用必须执行以下操作:

  • 在导航栏后绘制,实现更具吸引力的现代用户体验。
  • 在状态栏后绘制(如果对您的内容和布局有意义,例如在全宽图像的情况下)。为此,请使用 AppBarLayout 等 API,此类 API 定义了固定到屏幕顶部的应用栏。
图 1.采用无边框布局的系统栏。

如需在您的应用中实现全屏布局,请按以下步骤操作:

  1. 启用全屏显示。
  2. 处理所有视觉重叠。
一张图片,在状态栏后面显示某个应用的图片
图 2.在状态栏后面显示图像的应用示例。

启用全屏显示。

您可以通过在 ActivityonCreate 中调用 enableEdgeToEdge 来在应用中启用全屏显示屏。应在 setContentView 之前调用。

Kotlin

  override fun onCreate(savedInstanceState: Bundle?) {
    enableEdgeToEdge()
    super.onCreate(savedInstanceState)
    ...
  }

Java

  @Override
  protected void onCreate(@Nullable Bundle savedInstanceState) {
    EdgeToEdge.enable(this);
    super.onCreate(savedInstanceState);
    ...
  }

默认情况下,enableEdgeToEdge 会将系统栏设为透明,但在“三按钮”导航模式下,状态栏会显示半透明纱罩。系统图标和纱罩的颜色会根据系统浅色或深色主题来调整。

enableEdgeToEdge 方法会自动声明应用应全屏布局,并调整系统栏的颜色。如果出于任何原因需要这样做,请参阅“手动设置无边框显示屏”。

使用边衬区处理重叠

启用全屏显示后,应用的某些视图可能会在系统栏后绘制,如图 3 所示。

您可以通过响应边衬区(用于指定屏幕的哪些部分与系统界面(如导航栏或状态栏)相交)来解决重叠问题。相交可能意味着在内容上方显示,但也可以告知应用有关系统手势的信息。

适用于全屏显示应用的边衬区类型包括:

  • 系统栏边衬区:最适合可点按且不得被系统栏在视觉上遮挡的视图。

  • 系统手势边衬区:适用于系统用来优先于您的应用的手势导航区域。

系统栏边衬区

系统栏边衬区是最常用的边衬区类型。它们代表系统界面在 Z 轴上显示在应用上方的区域。它们最适合用于在应用中移动或填充可点按且不得被系统栏遮挡的视图。

例如,图 3 中的悬浮操作按钮 (FAB) 被导航栏部分遮挡:

显示已实现全屏显示,但导航栏覆盖了 FAB 的图片
图 3. 在无边框布局中,导航栏与 FAB 重叠。

为避免在手势模式或按钮模式下出现这种视觉重叠,您可以将 getInsets(int)WindowInsetsCompat.Type.systemBars() 结合使用来增加视图的外边距。

以下代码示例展示了如何实现系统栏边衬区:

Kotlin

ViewCompat.setOnApplyWindowInsetsListener(fab) { v, windowInsets ->
  val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
  // Apply the insets as a margin to the view. This solution sets
  // only the bottom, left, and right dimensions, but you can apply whichever
  // insets are appropriate to your layout. You can also update the view padding
  // if that's more appropriate.
  v.updateLayoutParams<MarginLayoutParams>(
      leftMargin = insets.left,
      bottomMargin = insets.bottom,
      rightMargin = insets.right,
  )

  // Return CONSUMED if you don't want want the window insets to keep passing
  // down to descendant views.
  WindowInsetsCompat.CONSUMED
}

Java

ViewCompat.setOnApplyWindowInsetsListener(fab, (v, windowInsets) -> {
  Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars());
  // Apply the insets as a margin to the view. This solution sets only the
  // bottom, left, and right dimensions, but you can apply whichever insets are
  // appropriate to your layout. You can also update the view padding if that's
  // more appropriate.
  MarginLayoutParams mlp = (MarginLayoutParams) v.getLayoutParams();
  mlp.leftMargin = insets.left;
  mlp.bottomMargin = insets.bottom;
  mlp.rightMargin = insets.right;
  v.setLayoutParams(mlp);

  // Return CONSUMED if you don't want want the window insets to keep passing
  // down to descendant views.
    return WindowInsetsCompat.CONSUMED;
});

如果您对图 3 所示的示例应用此解决方案,则不会在按钮模式下出现视觉重叠,如图 4 所示:

图片:显示未覆盖 FAB 的半透明导航栏
图 4. 解决了按钮模式下的视觉重叠问题。

这同样适用于手势导航模式,如图 5 所示:

一张图片,显示通过手势导航实现了无边框导航
图 5. 解决了手势导航模式下的视觉重叠问题。

系统手势边衬区

系统手势边衬区表示窗口中系统手势优先于您的应用的区域。在图 6 中,这些区域以橙色显示:

显示系统手势边衬区的图片
图 6. 系统手势边衬区。

与系统栏边衬区一样,您可以将 getInsets(int)WindowInsetsCompat.Type.systemGestures() 结合使用,以避免与系统手势边衬区重叠。

使用这些边衬区可将可滑动视图远离边缘。常见用例包括底部动作条、游戏中滑动以及使用 ViewPager2 实现的轮播界面。

在 Android 10 或更高版本中,系统手势边衬区包含用于主屏幕手势的底部边衬区,以及用于返回手势的左右边衬区:

显示系统手势边衬区测量值的图片
图 7. 系统手势边衬区测量结果。

以下代码示例展示了如何实现系统手势边衬区:

Kotlin

ViewCompat.setOnApplyWindowInsetsListener(view) { view, windowInsets ->
    val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemGestures())
    // Apply the insets as padding to the view. Here, set all the dimensions
    // as appropriate to your layout. You can also update the view's margin if
    // more appropriate.
    view.updatePadding(insets.left, insets.top, insets.right, insets.bottom)

    // Return CONSUMED if you don't want the window insets to keep passing down
    // to descendant views.
    WindowInsetsCompat.CONSUMED
}

Java

ViewCompat.setOnApplyWindowInsetsListener(view, (v, windowInsets) -> {
    Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemGestures());
    // Apply the insets as padding to the view. Here, set all the dimensions
    // as appropriate to your layout. You can also update the view's margin if
    // more appropriate.
    view.setPadding(insets.left, insets.top, insets.right, insets.bottom);

    // Return CONSUMED if you don't want the window insets to keep passing down
    // to descendant views.
    return WindowInsetsCompat.CONSUMED;
});

沉浸模式

建议在全屏模式下观看某些内容,以便为用户提供沉浸感更强的体验。您可以使用 WindowInsetsControllerWindowInsetsControllerCompat 库为沉浸模式隐藏系统栏:

Kotlin

val windowInsetsController =
      WindowCompat.getWindowInsetsController(window, window.decorView)

// Hide the system bars.
windowInsetsController.hide(Type.systemBars())

// Show the system bars.
windowInsetsController.show(Type.systemBars())

Java

Window window = getWindow();
WindowInsetsControllerCompat windowInsetsController =
      WindowCompat.getWindowInsetsController(window, window.getDecorView());
if (windowInsetsController == null) {
    return;
  }
// Hide the system bars.
windowInsetsController.hide(WindowInsetsCompat.Type.systemBars());

// Show the system bars.
windowInsetsController.show(WindowInsetsCompat.Type.systemBars());

如需详细了解如何实现此功能,请参阅隐藏系统栏以实现沉浸模式

其他资源

如需详细了解 WindowInsets、手势导航以及边衬区的工作原理,请参阅以下参考文档: