支持多窗口模式

多窗口模式允许多个应用同时共享同一屏幕。应用可以并排显示或一个在上一个在下(分屏模式),一个应用以一个小窗口覆盖其他应用(画中画模式),或者各个应用在单独的可移动、可调整大小的窗口中(自由形式模式)。

图 1. 在分屏模式下并排显示两个应用。

用户体验取决于 Android 版本和设备类型

  • Android 7.0(API 级别 24)在小屏幕设备上引入了分屏模式,在某些设备上引入了画中画模式。

    • 分屏模式使用两个应用填充屏幕,将它们并排显示或一个在上一个在下。用户可以拖动分隔两个应用的分隔线,使一个应用更大,另一个应用更小。

    • 画中画模式使用户能够在与其他应用交互时继续视频播放(请参阅画中画支持)。

    • 自由形式模式,其中用户可以自由调整每个活动的尺寸,可以由大屏幕设备的制造商启用。

      您可以通过指定活动的最小允许尺寸来配置应用如何处理多窗口模式。您还可以通过将resizeabableActivity="false"设置为确保系统始终以全屏显示您的应用来禁用应用的多窗口模式。

  • Android 8.0(API 级别 26)将画中画模式扩展到小屏幕设备。

  • Android 12(API 级别 31)使多窗口模式成为标准行为。

    • 在大屏幕上中等扩展窗口尺寸类别),平台支持多窗口模式下的所有应用,无论应用配置如何。如果resizeableActivity="false",则在必要时将应用置于兼容模式以适应显示尺寸。

    • 在小屏幕上紧凑窗口尺寸类别),系统会检查活动的minWidthminHeight以确定活动是否可以在多窗口模式下运行。如果resizeableActivity="false",则无论最小宽度和高度如何,都将阻止应用在多窗口模式下运行。

分屏模式

用户可以通过执行以下操作激活分屏模式

  1. 打开最近使用的屏幕
  2. 向上滑动一个应用以显示
  3. 按应用标题栏中的应用图标
  4. 选择分屏菜单选项
  5. 从最近使用的屏幕中选择另一个应用,或关闭最近使用的屏幕并运行另一个应用

用户可以通过将窗口分隔线拖动到屏幕边缘(向上或向下,向左或向右)来退出分屏模式。

启动相邻

如果您的应用需要通过意图访问内容,您可以使用FLAG_ACTIVITY_LAUNCH_ADJACENT在相邻的分屏窗口中打开内容。

FLAG_ACTIVITY_LAUNCH_ADJACENT是在 Android 7.0(API 级别 24)中引入的,用于使在分屏模式下运行的应用能够在相邻窗口中启动活动。

Android 12L(API 级别 32)及更高版本已扩展了该标志的定义,以使以全屏模式运行的应用能够激活分屏模式,然后在相邻窗口中启动活动。

要启动相邻活动,请将FLAG_ACTIVITY_LAUNCH_ADJACENTFLAG_ACTIVITY_NEW_TASK结合使用,例如

Kotlin

fun openUrlInAdjacentWindow(url:
String) { Intent(Intent.ACTION_VIEW).apply { data = Uri.parse(url)
addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT or Intent.FLAG_ACTIVITY_NEW_TASK)
 }.also { intent -> startActivity(intent) } }

Java

public void openUrlInAdjacentWindow(String url) {
  Intent intent = new Intent(Intent.ACTION_VIEW);
  intent.setData(Uri.parse(url));
  intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT | Intent.FLAG_ACTIVITY_NEW_TASK);
  startActivity(intent);
}

多窗口模式下的活动生命周期

多窗口模式不会更改活动生命周期。但是,多个窗口中应用的恢复状态在不同版本的 Android 上有所不同。

多恢复

Android 10(API 级别 29)及更高版本支持多恢复——当设备处于多窗口模式时,所有活动都保持在RESUMED状态。如果透明活动位于活动顶部或活动不可聚焦,例如活动处于画中画模式,则活动可能会暂停。也可能在给定时间没有活动获得焦点,例如,如果通知抽屉已打开。onStop()方法照常工作:该方法在活动从屏幕上移除时始终会被调用。

在运行 Android 9(API 级别 28)的某些设备上也可以使用多恢复。要在 Android 9 设备上选择加入多恢复,请添加以下清单元数据

<meta-data android:name="android.allow_multiple_resumed_activities" android:value="true" />

要验证给定设备是否支持此清单元数据,请参阅设备规格。

Android 9

在 Android 9(API 级别 28)及更低版本上的多窗口模式下,在给定时间只有用户最近交互过的活动处于活动状态。此活动被认为是最顶层的,并且是唯一处于RESUMED状态的活动。所有其他可见活动都处于STARTED状态,但未处于RESUMED状态。但是,系统会为这些可见但未恢复的活动提供比不可见活动更高的优先级。如果用户与其中一个可见活动进行交互,则该活动将恢复,而先前最顶层的活动将进入STARTED状态。

当单个活动应用进程中存在多个活动时,z 顺序最高的活动将恢复,其他活动将暂停。

配置更改

当用户将应用置于多窗口模式时,系统会通知活动配置更改,如处理配置更改中所述。当用户调整应用大小或将应用放回全屏模式时,也会发生这种情况。

从本质上讲,此更改具有与系统通知应用设备已从纵向切换到横向方向时相同活动生命周期含义,只是应用尺寸已更改,而不是仅仅交换。您的活动可以自行处理配置更改,或者您的应用可以允许系统销毁活动并使用新尺寸重新创建它。

如果用户正在调整窗口大小并在任一维度上使其更大,则系统会调整活动大小以匹配用户操作并根据需要发出配置更改。如果应用在绘制新公开的区域方面滞后,则系统会使用windowBackground属性或默认windowBackgroundFallback样式属性中指定的颜色临时填充这些区域。

独占资源访问

为了帮助支持多恢复功能,请使用onTopResumedActivityChanged()生命周期回调。

当活动获得或失去最顶层恢复活动位置时,将调用该回调,这在活动使用共享单例资源(例如麦克风或摄像头)时非常重要

Kotlin

override fun
onTopResumedActivityChanged(topResumed: Boolean) { if (topResumed) { // Top
resumed activity. // Can be a signal to re-acquire exclusive resources. } else {
// No longer the top resumed activity. } }

Java

@Override
public void onTopResumedActivityChanged(boolean topResumed) {
  if (topResumed) {
      // Top resumed activity.
      // Can be a signal to re-acquire exclusive resources.
  } else {
      // No longer the top resumed activity.
  }
}

请注意,应用可能会因其他原因而丢失资源,例如共享硬件部件的移除。

无论如何,应用都应优雅地处理影响可用资源的事件和状态更改。

对于使用摄像头的应用,CameraManager.AvailabilityCallback#onCameraAccessPrioritiesChanged()提供了一个提示,表明可能是尝试获取摄像头访问权限的好时机。此方法自 Android 10(API 级别 29)起可用。

请记住,resizeableActivity=false不能保证独占摄像头访问权限,因为其他使用摄像头的应用可以在其他显示器上打开。

图 2. 多窗口模式下的摄像头。

您的应用在失去焦点时不一定需要释放相机。例如,您可能希望在用户与新获得焦点的最顶层恢复的应用交互时继续进行相机预览。您的应用在不是最顶层恢复的应用时继续运行相机是可以的,但它必须正确处理断开连接的情况。当最顶层恢复的应用想要使用相机时,它可以打开相机,而您的应用将失去访问权限。您的应用可以在应用重新获得焦点时重新打开相机。

在应用收到 CameraDevice.StateCallback#onDisconnected() 回调后,对相机设备的后续调用将抛出 CameraAccessException

多显示器

Android 10(API 级别 29)支持辅助显示器上的活动。如果活动在具有多个显示器的设备上运行,用户可以将活动从一个显示器移动到另一个显示器。多恢复 也适用于多屏幕场景;多个活动可以同时接收用户输入。

应用可以在启动时或创建另一个活动时指定其应在哪个显示器上运行。此行为取决于清单文件中定义的活动启动模式以及启动活动的实体设置的 intent 标志和选项。有关更多详细信息,请参阅 ActivityOptions 类。

当活动移动到辅助显示器时,它可能会经历上下文更新、窗口大小调整以及配置和资源更改。如果活动处理配置更改,则会在 onConfigurationChanged() 中通知活动;否则,活动将重新启动。

如果处理配置更改,活动应在 onCreate()onConfigurationChanged() 中检查当前显示器。确保在显示器更改时更新资源和布局。

如果活动的所选启动模式允许多个实例,则在辅助屏幕上启动可能会创建活动的新实例。这两个活动同时恢复。

图 3.多个显示器上的多个活动实例。

您可能还想了解 Android 8.0 中引入的 多显示器 API。

活动与应用上下文

在多显示器中使用正确的上下文至关重要。在访问资源时,活动上下文(正在显示的)与应用上下文(未显示的)不同。

活动上下文包含有关显示器的信息,并且始终针对活动显示的显示器区域进行调整。这使您能够获取有关应用的显示器密度或窗口指标的正确信息。您应该始终使用活动上下文(或其他基于 UI 的上下文)来获取有关当前窗口或显示器的信息。这也会影响使用上下文信息的一些系统 API(例如,请参阅 Toast 概述)。

活动窗口配置和父显示器定义资源和上下文。按如下方式获取当前显示器

Kotlin

val activityDisplay = activity.getDisplay()

Java

Display activityDisplay = activity.getDisplay();

获取当前活动窗口指标

Kotlin

val windowMetrics = activity.getWindowManager().getCurrentWindowMetrics()

Java

WindowMetrics windowMetrics = activity.getWindowManager().getCurrentWindowMetrics();

获取当前系统配置的最大窗口指标

Kotlin

val maximumWindowMetrics = activity.getWindowManager().getMaximumWindowMetrics()

Java

WindowMetrics maximumWindowMetrics = activity.getWindowManager().getMaximumWindowMetrics();

最大窗口指标用于进行计算、布局选择或确定提前获取资源的大小。在 onCreate() 中提供此功能使您能够在第一次布局传递之前做出这些决定。这些指标不应用于布局特定的视图元素;而是使用 Configuration 对象中的信息。

显示器挖孔

折叠式设备在折叠和展开时可能具有不同的挖孔几何形状。要避免挖孔问题,请参阅 支持显示器挖孔

辅助显示器

您可以从 DisplayManager 系统服务中获取可用的显示器

Kotlin

val displayManager =
getSystemService(Context.DISPLAY_SERVICE) as DisplayManager val displays =
displayManager.getDisplays()

Java

DisplayManager displayManager = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE);
Display[] displays = displayManager.getDisplays();

使用 Display 类获取有关特定显示器的信息,例如显示器大小或指示显示器是否安全的 标志。但是,不要假设显示器大小将与分配给您的应用的显示器区域相同。请记住,在多窗口模式下,您的应用占据显示器的一部分。

确定活动是否可以在显示器上启动

Kotlin

val activityManager =
getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager val
activityAllowed = activityManager.isActivityStartAllowedOnDisplay(context,
displayId, intent)

Java

ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
boolean activityAllowed = activityManager.isActivityStartAllowedOnDisplay(context, displayId, intent);

然后在显示器上启动活动

Kotlin

val options = ActivityOptions.makeBasic()
options.setLaunchDisplayId(targetDisplay.displayId) startActivity(intent,
options.toBundle())

Java

ActivityOptions options = ActivityOptions.makeBasic();
options.setLaunchDisplayId(targetDisplay.displayId);
startActivity(intent, options.toBundle());

多显示器支持

Android 为软件键盘、壁纸和启动器提供多显示器支持。

软件键盘

如果显示器配置为支持系统装饰,则可以在辅助屏幕上显示键盘。如果文本字段在该显示器上请求输入,则输入法编辑器会自动出现。

图 4.辅助显示器上的键盘。

壁纸

在 Android 10(API 级别 29)中,辅助屏幕可以有壁纸。框架为每个显示器创建 WallpaperService.Engine 的单独实例。确保每个引擎的表面独立绘制。开发人员可以使用 WallpaperService.Engine#getDisplayContext() 中的显示器上下文加载资源。此外,请确保您的 WallpaperInfo.xml 文件设置 android:supportsMultipleDisplays="true"

图 5.手机和辅助显示器上的壁纸。

启动器

一个新的 intent 过滤器类别 SECONDARY_HOME 为辅助屏幕提供了一个专用的活动。该活动的实例用于所有支持系统装饰的显示器,每个显示器一个。

<activity>
    ...
    <intent-filter>
        <category android:name="android.intent.category.SECONDARY_HOME" />
        ...
    </intent-filter>
</activity>

活动必须具有不阻止多个实例并且可以适应不同屏幕尺寸的启动模式。启动模式不能是 singleInstancesingleTask

例如,Launcher3 的 AOSP 实现支持 SECONDARY_HOME 活动。

图 6.手机上的 Material Design 启动器。
图 7.辅助显示器上的 Material Design 启动器。

窗口指标

Android 11(API 级别 30)引入了以下 WindowManager 方法来提供在多窗口模式下运行的应用的边界

Jetpack WindowManager 库方法 computeCurrentWindowMetrics()computeMaximumWindowMetrics() 分别提供了类似的功能,但具有向后兼容到 API 级别 14 的功能。

要获取除当前显示器之外的显示器的指标,请执行以下操作(如代码片段所示)

  • 创建显示器上下文
  • 为显示器创建窗口上下文
  • 获取窗口上下文的 WindowManager
  • 获取应用可用的最大显示区域的 WindowMetrics

Kotlin

val windowMetrics =
context.createDisplayContext(display)
.createWindowContext(WindowManager.LayoutParams.TYPE_APPLICATION, null)
.getSystemService(WindowManager::class.java) .maximumWindowMetrics

Java

WindowMetrics windowMetrics = context.createDisplayContext(display)
                            .createWindowContext(WindowManager.LayoutParams.TYPE_APPLICATION, null)
                            .getSystemService(WindowManager.class)
                            .getMaximumWindowMetrics();

已弃用的方法

Display 方法 getSize()getMetrics() 在 API 级别 30 中被弃用,取而代之的是新的 WindowManager 方法。

Android 12(API 级别 31)弃用 Display 方法 getRealSize()getRealMetrics() 并更新其行为以更接近于 getMaximumWindowMetrics() 的行为。

多窗口模式配置

如果您的应用面向 Android 7.0(API 级别 24)或更高版本,您可以配置应用的活动如何以及是否支持多窗口模式。您可以在清单中设置属性来控制大小和布局。根活动的属性设置适用于其任务堆栈中的所有活动。例如,如果根活动具有 android:resizeableActivity="true",则任务堆栈中的所有活动都可调整大小。在某些较大的设备(例如 Chromebook)上,即使您指定 android:resizeableActivity="false",您的应用也可能在可调整大小的窗口中运行。如果这会破坏您的应用,您可以使用 Google Play 上的过滤器 来限制您的应用在这些设备上的可用性。

Android 12(API 级别 31)默认为多窗口模式。在大屏幕(中等扩展 窗口大小类)上,所有应用都在多窗口模式下运行,无论应用配置如何。在小屏幕上,系统会检查活动的 minWidthminHeightresizeableActivity 设置以确定活动是否可以在多窗口模式下运行。

resizeableActivity

在清单的 <activity><application> 元素中设置此属性以启用或禁用 API 级别 30 及更低版本的多分辨率模式

<application
  android:name=".MyActivity"
  android:resizeableActivity=["true" | "false"] />;

如果此属性设置为 true,则可以在分屏和自由形式模式下启动活动。如果属性设置为 false,则活动不支持多窗口模式。如果值为 false,并且用户尝试在多窗口模式下启动活动,则活动将占据整个屏幕。

如果您的应用面向 API 级别 24 或更高版本,但您未为此属性指定值,则该属性的值默认为 true。

如果您的应用面向 API 级别 31 或更高版本,则此属性在小屏幕和大屏幕上的工作方式不同

  • 大屏幕中等扩展 窗口大小类):所有应用都支持多窗口模式。该属性指示活动是否可以调整大小。如果 resizeableActivity="false",则在必要时将应用置于兼容模式以符合显示尺寸。

  • 小屏幕紧凑型窗口尺寸类别):如果 resizeableActivity="true" 且 Activity 的最小宽度和最小高度在多窗口要求范围内,则 Activity 支持多窗口模式。如果 resizeableActivity="false",则无论 Activity 的最小宽度和高度如何,Activity 都不支持多窗口模式。

supportsPictureInPicture

在清单的 <activity> 节点中设置此属性,以指示 Activity 是否支持画中画模式。

<activity
  android:name=".MyActivity"
  android:supportsPictureInPicture=["true" | "false"] />

configChanges

要自己处理多窗口配置更改(例如,当用户调整窗口大小时),请将 android:configChanges 属性添加到应用清单的 <activity> 节点中,并至少包含以下值

<activity
  android:name=".MyActivity"
  android:configChanges="screenSize | smallestScreenSize
      | screenLayout | orientation" />

添加 android:configChanges 后,您的 Activity 和 Fragment 会收到对 onConfigurationChanged() 的回调,而不是被销毁和重新创建。然后,您可以根据需要手动更新视图、重新加载资源并执行其他操作。

<layout>

在 Android 7.0(API 级别 24)及更高版本中,<layout> 清单元素支持几个影响 Activity 在多窗口模式下行为的属性

  • android:defaultHeightandroid:defaultWidth:Activity 在自由形式模式下启动时的默认高度和宽度。

  • android:gravity:Activity 在自由形式模式下启动时的初始放置位置。请参阅 Gravity 类以获取合适的属性值。

  • android:minHeightandroid:minWidth:Activity 在分屏模式和自由形式模式下的最小高度和最小宽度。如果用户在分屏模式下移动分隔线使 Activity 小于指定的最小值,则系统会将 Activity 裁剪到用户请求的大小。

以下代码展示了如何在 Activity 以自由形式模式显示时指定其默认大小和位置以及最小大小

<activity android:name=".MyActivity">
    <layout android:defaultHeight="500dp"
          android:defaultWidth="600dp"
          android:gravity="top|end|..."
          android:minHeight="450dp"
          android:minWidth="300dp" />
</activity>

运行时多窗口模式

从 Android 7.0 开始,系统提供了支持可在多窗口模式下运行的应用的功能。

多窗口模式下禁用的功能

在多窗口模式下,Android 可能会禁用或忽略不适用于与其他 Activity 或应用共享设备屏幕的 Activity 的功能。

此外,某些系统 UI 自定义选项也被禁用。例如,如果应用在多窗口模式下运行,则无法隐藏状态栏(请参阅 控制系统 UI 可见性)。

系统会忽略对 android:screenOrientation 属性的更改。

多窗口模式查询和回调

Activity 类提供了以下方法来支持多窗口模式

  • isInMultiWindowMode():指示 Activity 是否处于多窗口模式。

  • isInPictureInPictureMode():指示 Activity 是否处于画中画模式。

  • onMultiWindowModeChanged():每当 Activity 进入或退出多窗口模式时,系统都会调用此方法。如果 Activity 正在进入多窗口模式,则系统会向方法传递值 true;如果 Activity 正在离开多窗口模式,则系统会传递值 false。

  • onPictureInPictureModeChanged():每当 Activity 进入或退出画中画模式时,系统都会调用此方法。如果 Activity 正在进入画中画模式,则系统会向方法传递值 true;如果 Activity 正在离开画中画模式,则系统会传递值 false。

Fragment 类公开了许多此类方法的版本;例如,Fragment.onMultiWindowModeChanged()

画中画模式

要将 Activity 置于画中画模式,请调用 enterPictureInPictureMode()。如果设备不支持画中画模式,则此方法无效。有关更多信息,请参阅 使用画中画 (PiP) 添加视频

多窗口模式下的新 Activity

启动新 Activity 时,您可以指示新 Activity 应尽可能显示在当前 Activity 旁边。使用 Intent 标志 FLAG_ACTIVITY_LAUNCH_ADJACENT,它会告诉系统尝试在相邻窗口中创建新 Activity,以便这两个 Activity 共享屏幕。系统会尽力做到这一点,但不能保证一定能实现。

如果设备处于自由形式模式并且您要启动新 Activity,则可以通过调用 ActivityOptions.setLaunchBounds() 指定新 Activity 的尺寸和屏幕位置。如果设备未处于多窗口模式,则此方法无效。

在 API 级别 30 及以下版本中,如果在任务堆栈中启动 Activity,则 Activity 会替换屏幕上的 Activity,并继承其所有多窗口属性。如果要将新 Activity 作为多窗口模式下的单独窗口启动,则必须在新的任务堆栈中启动它。

Android 12(API 级别 31)使应用能够在其多个 Activity 之间拆分应用的任务窗口。您可以通过创建 XML 配置文件或进行 Jetpack WindowManager API 调用来确定应用如何显示其 Activity——全屏、并排或堆叠。

拖放

当两个 Activity 共享屏幕时,用户可以将数据从一个 Activity 拖放到另一个 Activity。(在 Android 7.0 之前,用户只能在一个 Activity 内拖放数据。)要快速添加对接受已删除内容的支持,请参阅 DropHelper API。有关完整的拖放指南,请参阅 启用拖放

多实例

每个根 Activity 都有自己的任务,该任务在单独的进程中运行并在其自己的窗口中显示。要以单独的窗口启动应用的新实例,您可以使用 FLAG_ACTIVITY_NEW_TASK 标志启动新 Activity。您可以将此与一些 多窗口属性 结合使用以请求新窗口的特定位置。例如,购物应用可以显示多个窗口来比较商品。

Android 12(API 级别 31)使您能够在同一任务窗口中并排启动 Activity 的两个实例。

如果要允许用户从应用启动器或任务栏启动应用的另一个实例,请确保启动器 Activity 设置了 android:resizeableActivity="true" 并且不使用阻止多个实例的启动模式。例如,当设置了 FLAG_ACTIVITY_MULTIPLE_TASKFLAG_ACTIVITY_NEW_DOCUMENT 时,singleInstancePerTask Activity 可以在不同的任务中多次实例化。

不要将多实例与多面板布局混淆,例如使用 SlidingPaneLayout列表详细信息呈现,后者在单个窗口内运行。

请注意,当多个实例在可折叠设备上的单独窗口中运行时,如果姿势发生变化,则一个或多个实例可能会被发送到后台。例如,假设设备展开并且有两个应用实例在折叠的两侧的两个窗口中运行。如果设备折叠,则其中一个实例可能会被终止,而不是尝试将两个实例的窗口都适合较小的屏幕。

多窗口模式验证

无论您的应用是否面向 API 级别 24 或更高版本,您都应验证其在多窗口模式下的行为,以防用户尝试在运行 Android 7.0 或更高版本的设备上以多窗口模式启动它。

测试设备

运行 Android 7.0(API 级别 24)或更高版本的设备支持多窗口模式。

API 级别 23 或更低版本

当用户尝试在多窗口模式下使用应用时,系统会强制调整应用大小,除非应用声明了固定方向。

如果您的应用未声明固定方向,则应在运行 Android 7.0 或更高版本的设备上启动应用,并尝试将其置于分屏模式。验证应用在强制调整大小时的用户体验是否可以接受。

如果应用声明了固定方向,则应尝试将其置于多窗口模式。验证这样做时,应用是否保持全屏模式。

API 级别 24 到 30

如果您的应用面向 API 级别 24 到 30 并且未禁用多窗口支持,请在分屏模式和自由形式模式下验证以下行为

  • 以全屏模式启动应用,然后通过长按最近使用的应用按钮切换到多窗口模式。验证应用是否已正确切换。

  • 直接以多窗口模式启动应用,并验证应用是否已正确启动。您可以通过按最近使用的应用按钮,然后长按应用的标题栏并将其拖动到屏幕上的突出显示区域之一来以多窗口模式启动应用。

  • 通过拖动屏幕分隔线在分屏模式下调整应用大小。验证应用是否已在不崩溃的情况下调整大小,以及必要的 UI 元素是否可见。

  • 如果已为应用指定了最小尺寸,则尝试调整应用大小,使其窗口大小小于这些尺寸。验证是否无法将应用调整为小于指定的最小尺寸。

  • 在所有测试中,验证应用的性能是否可以接受。例如,验证在调整应用大小时更新 UI 是否没有太长的延迟。

API 级别 31 或更高版本

如果您的应用面向 API 级别 31 或更高版本,并且主 Activity 的最小宽度和最小高度小于或等于可用显示区域的相应尺寸,请验证 API 级别 24 到 30 中列出的所有行为。

测试清单

要验证您的应用在多窗口模式下的性能,请尝试以下操作。除非另有说明,否则您应该在分屏模式和自由形式模式下都尝试这些操作。

  • 进入和退出多窗口模式。

  • 从您的应用切换到另一个应用,并验证应用在可见但未处于活动状态时是否行为正常。例如,如果您的应用正在播放视频,请验证用户与另一个应用交互时视频是否继续播放。

  • 在分屏模式下,尝试移动屏幕分隔线以使您的应用变大或变小。尝试在并排和一个在上一个在下两种配置中执行这些操作。验证应用不会崩溃,基本功能可见,并且调整大小操作不会花费太长时间。

  • 连续执行多次调整大小操作。验证您的应用不会崩溃或内存泄漏。Android Studio 的内存分析器提供了有关应用内存使用情况的信息(请参阅使用内存分析器检查应用的内存使用情况)。

  • 在许多不同的窗口配置中正常使用您的应用,并验证应用是否行为正常。验证文本是否可读,并且 UI 元素不会太小而无法交互。

多窗口支持已禁用

在 API 级别 24 到 30 上,如果您通过设置android:resizeableActivity="false"禁用了多窗口支持,则应在运行 Android 7.0 到 11 的设备上启动您的应用,并尝试将其置于分屏和自由形式模式。验证执行此操作时,应用是否保持全屏模式。

其他资源

有关 Android 中多窗口支持的更多信息,请参阅

为您推荐 * 注意:当 JavaScript 关闭时显示链接文本 * 设备兼容性模式 * 支持大屏幕可调整大小 * 处理配置更改