多窗口支持

多窗口模式允许多个应用同时共享同一屏幕;让系统可以左右或上下并排显示应用(分屏模式),在应用中用小窗口叠加显示其他应用(画中画模式),或者在可移动且可调整大小的单独窗口中显示各个应用(自由窗口模式)。

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

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

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

    分屏模式会以左右并排或上下并排的方式分屏显示两个应用。用户可以拖动两个应用之间的分隔线,放大其中一个应用,同时缩小另一个应用。

    画中画模式可让用户在与另一个应用互动的同时继续播放视频(详见对画中画的支持)。

    大屏设备的制造商可启用自由窗口模式。在该模式下,用户可以自由调整各 activity 的大小。

    您可以通过指定 activity 允许的最小尺寸,配置应用处理多窗口模式的方式。您还可以通过设置 resizeableActivity="false" 来为应用停用多窗口模式,确保系统始终以全屏模式显示应用。

  • Android 8.0(API 级别 26)将画中画模式扩展到了小屏幕设备。
  • Android 12(API 级别 31)将多窗口模式作为标准行为。

    在大屏 (sw >= 600dp) 设备上,不论应用配置为何,平台都支持在多窗口模式下运行所有应用。如果 resizeableActivity="false",应用会在必要时进入兼容模式,以适应显示屏尺寸。

    在小屏 (sw < 600dp) 设备上,系统会检查 activity 的 minWidthminHeight,以确定该 activity 能否在多窗口模式下运行。如果 resizeableActivity="false",则无论最小宽度和高度是多少,应用都无法在多窗口模式下运行。

    注意:设备制造商可以替换这些行为。

分屏模式

用户可以通过执行以下操作来启用分屏模式:

  1. 打开“最近”屏幕
  2. 将某个应用滑动到视图中
  3. 按应用标题栏中的应用图标
  4. 选择分屏菜单选项
  5. 从“最近”屏幕中选择另一个应用,或者关闭“最近”屏幕并运行另一个应用

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

启动 adjacent

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

Android 7.0(API 级别 24)中引入的 FLAG_ACTIVITY_LAUNCH_ADJACENT 就能让分屏模式下运行的应用在相邻的窗口中启动 activity。

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

如需启动相邻的 activity,请将 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);
}

多窗口模式下的 activity 生命周期

多窗口模式不会更改 activity 生命周期。不过,在不同版本的 Android 系统中,应用在多个窗口中的恢复状态会有所不同。

多项恢复

Android 10(API 级别 29)及更高版本支持多项恢复模式:当设备处于多窗口模式时,所有 activity 都会保持 RESUMED 状态。如果某个 activity 上方有一个透明 activity 或者该 activity 不可聚焦(例如,处于画中画模式),则可以暂停该 activity。还有一种可能是,在某个时间,系统没有聚焦在任何 activity 上,例如,当抽屉式通知栏打开时。onStop 方法会照常运行;每当 activity 从屏幕上移除时,系统都会调用该方法。

部分搭载 Android 9(API 级别 28)的设备也提供多项恢复模式。如需在 Android 9 设备上选择启用多项恢复模式,请添加以下清单元数据:

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

如需确认给定设备是否支持此清单元数据,请参阅设备规格。

Android 9

在 Android 9(API 级别 28)及更低版本上的多窗口模式下,在任意时间点都只有用户最近一次互动的 activity 处于活动状态。此 activity 被视为最顶层的 activity,而且是唯一处于 RESUMED 状态的 activity。所有其他可见的 activity 均处于 STARTED 而非 RESUMED 状态。不过,这些可见但并不处于 RESUMED 状态的 activity 在系统中享有比不可见 activity 更高的优先级。如果用户与其中一个可见的 activity 互动,那么该 activity 将进入 RESUMED 状态,而之前的最顶层 activity 将进入 STARTED 状态。

如果一个处于活动状态的应用进程中有多个 activity,则 Z 轴顺序最高的 activity 为 RESUMED 状态,其他 activity 为 PAUSED 状态。

配置变更

处理配置更改中所述,当用户将应用置于多窗口模式下时,系统会通知 activity 发生的配置更改。当用户调整应用大小或将应用恢复到全屏模式时,系统也会通知发生了配置更改。

该更改与系统通知应用设备已从竖屏模式切换到横屏模式时的 activity 生命周期影响基本相同,区别在于设备不仅仅是切换了方向,还更改了尺寸。如处理配置更改中所述,您的 activity 可以自行处理配置更改,或允许系统销毁 activity,并以新的尺寸重新创建该 activity。

如果用户调整窗口大小以增加窗口的高度或宽度,那么系统会调整 activity 的大小来配合用户操作,同时根据需要执行配置更改。如果应用在新公开区域的绘制滞后,系统会使用 windowBackground 属性或默认 windowBackgroundFallback 样式属性指定的颜色临时填充这些区域。

专属资源访问权限

为了帮助支持多项恢复功能,我们提供了一个新的生命周期回调 onTopResumedActivityChanged()

当 activity 获得或失去在顶层处于 RESUMED 状态的位置时,系统会调用此方法。请务必了解 activity 会在何时使用共享的单例资源(如麦克风或摄像头)。

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)支持辅助显示屏上的 activity。如果 activity 在具有多个显示屏的设备上运行,则用户可以将 activity 从一个显示屏移到另一个显示屏。多项恢复功能也适用于跨屏场景;多个 activity 可以同时接收用户输入。

应用可以指定在启动或创建其他 activity 时它应该在哪个显示屏上运行。此行为取决于清单文件以及 intent 标志和选项(由启动 activity 的实体设置)中定义的 activity 启动模式。如需了解详情,请参阅 ActivityOptions

当 activity 移至辅助显示屏时,系统会更新上下文,调整窗口大小,并更改配置和资源。如果由该 activity 来处理配置更改,它会在 onConfigurationChanged() 中收到通知;如果不是,它会重新启动。

如果配置更改已处理,activity 应该在 onCreateonConfigurationChanged 中检查当前显示屏。确保在更改显示屏时更新资源和布局。

如果为 activity 选择的启动模式支持多个实例,那么在辅助屏幕上启动将会创建一个新的 activity 实例。这两个 activity 会同时恢复。

同一个 activity 在多个显示屏中的多个实例。

图 3. 同一个 activity 在多个显示屏中的多个实例。

此外,不妨了解在 Android 8.0 中引入的多显示屏 API。

activity 上下文与应用上下文

在多屏幕模式下,使用适当的上下文至关重要。访问资源时,activity 上下文(已显示)与应用上下文(未显示)不同。

activity 上下文包含有关显示屏的信息,且始终会针对该 activity 所在的显示屏区域进行调整。这样,您便可以获得有关应用当前具备的显示屏密度或窗口指标的正确信息。您应始终使用 activity 上下文(或其他基于界面的上下文)来获取有关当前窗口或显示屏的信息。此外,这还会影响某些使用上下文提供的信息的系统 API(有关示例,请参阅消息框概览)。

activity 窗口配置和父显示屏会定义资源和上下文。获取当前显示屏,所用代码如下所示:

Kotlin

val activityDisplay = activity.getDisplay()

Java

Display activityDisplay = activity.getDisplay();

获取当前 activity 窗口指标:

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 类获取有关特定显示屏的信息,例如显示屏尺寸或指示显示屏是否安全的标志。不过,不要假定显示屏尺寸将与分配给应用的显示屏区域相同。请注意,在多窗口模式下,应用会占用显示屏的一部分。

确定 activity 能否在显示屏上启动:

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);

然后,在显示屏上启动该 activity:

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)中,壁纸可以显示在辅助屏幕上。Android 框架会分别为每个显示屏创建单独的 WallpaperService.Engine 实例。请确保每个引擎的外观都是独立绘制的。开发者可以使用 WallpaperService.Engine#getDisplayContext() 中的显示屏上下文加载资源。此外,请确保您的 WallpaperInfo.xml 文件设置了 android:supportsMultipleDisplays="true"

手机和辅助显示屏上的壁纸。

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

启动器

新的 intent 过滤器类别 SECONDARY_HOME 会为辅助屏幕提供专用 activity。该 activity 的各个实例可用在支持系统装饰的所有显示屏上,每个显示屏对应一个实例。

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

activity 的启动模式必须符合以下条件:不会阻止多个实例,并且可以适应不同屏幕尺寸。启动模式不能是 singleInstancesingleTask

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

手机上的 Material Design 启动器。

图 6. 手机上的 Material Design 启动器。

辅助显示屏上的 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)或更高版本为目标平台,就可以配置应用的 activity 是否支持多窗口模式以及如何支持。您可以在清单中设置属性来控制尺寸和布局。根 activity 的属性设置会应用于其任务堆栈中的所有 activity。例如,如果根 activity 设置了 android:resizeableActivity="true",那么任务堆栈中的所有 activity 均可调整大小。在 Chromebook 等一些较大的设备上,即使您指定了 android:resizeableActivity="false",您的应用也可能会在可调整大小的窗口中运行。如果这会破坏您的应用,您可以使用过滤器来限制您的应用在此类设备上的可用性。

Android 12(API 级别 31)默认采用多窗口模式。在大屏 (sw >= 600dp) 设备上,不论应用配置为何,所有应用都会在多窗口模式下运行。在小屏设备上,系统会检查 activity 的 minWidthminHeightresizeableActivity 设置以确定该 activity 能否在多窗口模式下运行。

resizeableActivity

在清单的 <activity><application> 元素中设置此属性,即可针对 API 级别 30 及更低级别启用或停用多窗口模式:

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

如果将此属性设置为 true,则 activity 能以分屏模式和自由窗口模式启动。如果将此属性设置为 false,则 activity 不支持多窗口模式。如果此值为 false,并且用户尝试在多窗口模式下启动 activity,则 activity 会全屏显示。

如果您的应用以 API 级别 24 或更高级别为目标平台,但您未指定此属性的值,则其值默认设为 true。

如果您的应用以 API 级别 31 或更高级别为目标平台,则此属性在小屏设备和大屏设备上的运作方式会有所不同:

  • 大屏 (sw >= 600dp) 设备:所有应用都支持多窗口模式。该属性用于指示是否可以调整 activity 的大小。如果 resizeableActivity="false",应用会在必要时进入兼容模式,以与显示屏尺寸相符。
  • 小屏 (sw < 600dp) 设备:如果 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 的功能。

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

系统将忽略对 android:screenOrientation 属性所做的更改。

多窗口模式查询和回调

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

isInMultiWindowMode()
用于指示 activity 是否处于多窗口模式。
isInPictureInPictureMode()

指示 activity 是否处于画中画模式。

注意:画中画模式是多窗口模式的特例。如果 myActivity.isInPictureInPictureMode() 返回 true,那么 myActivity.isInMultiWindowMode() 也会返回 true。

onMultiWindowModeChanged()
每当 activity 进入或退出多窗口模式时,系统都会调用此方法。当 activity 进入多窗口模式时,系统会向该方法传递 true 值;退出多窗口模式时,则传递 false 值。
onPictureInPictureModeChanged()
每当 activity 进入或退出画中画模式时,系统都会调用此方法。当 activity 进入画中画模式时,系统会向该方法传递 true 值;退出画中画模式时,则传递 false 值。

对于以上的很多方法,Fragment 类公开了多个版本,例如 Fragment.onMultiWindowModeChanged()

画中画模式

如要将 activity 置于画中画模式,请调用 enterPictureInPictureMode()。如果设备不支持画中画模式,则调用此方法不会产生任何影响。如需了解详情,请参阅画中画支持

多窗口模式下的新 activity

启动新 activity 时,您可以指示应尽可能将新 activity 显示在当前 activity 旁边。请使用 intent 标志 FLAG_ACTIVITY_LAUNCH_ADJACENT,告知系统尽量在相邻的窗口中创建新 activity,以便两个 activity 共享屏幕。系统会尽可能做到这一点,但无法保证最终结果。

如果设备处于自由窗口模式,则在启动新 activity 时,您可通过调用 ActivityOptions.setLaunchBounds() 来指定新 activity 的尺寸和屏幕位置。如果设备未处于多窗口模式,则调用该方法不会产生任何影响。

在 API 级别 30 及更低级别中,如果您在任务堆栈中启动 activity,该 activity 会替换屏幕上的 activity,并沿用其所有的多窗口模式属性。如果您要在多窗口模式下以单独的窗口启动新 activity,那么必须在新的任务堆栈中启动此 activity。

Android 12(API 级别 31)允许应用在多个 activity 之间拆分应用的任务窗口。您通过创建 XML 配置文件或进行 Jetpack WindowManager API 调用来确定应用如何显示其 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_DOCUMENTsingleInstancePerTask activity 可以在不同任务中多次实例化。

请不要将多实例与在单个窗口内运行的多面板布局(例如使用 SlidingPaneLayout列表-详情布局)混淆。

请注意,当多个实例在可折叠设备上的单独窗口中运行时,折叠状态更改可能会导致一个或多个实例移至后台。例如,假设一台设备已展开,并且有两个应用实例在折叠任一侧的两个窗口中运行。如果设备处于折叠状态,系统可能会终止其中的一个实例,而不是在较小的屏幕上尝试使窗口适应两个实例。

多窗口模式验证

无论您的应用是否以 API 级别 24 或更高级别为目标平台,您都应验证应用在多窗口模式下的行为,以防用户尝试在搭载 Android 7.0 或更高版本的设备上以多窗口模式启动应用。

测试设备

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

API 级别 23 或更低级别

当用户尝试在多窗口模式下使用应用时,系统将强制调整应用尺寸(除非应用声明使用固定的屏幕方向)。

如果您的应用未声明使用固定的屏幕方向,您应在搭载 Android 7.0 或更高版本的设备上启动应用,并尝试将应用置于分屏模式。确认应用被强制调整大小后,能提供可接受的用户体验。

如果您的应用声明使用固定的屏幕方向,您应尝试将应用置于多窗口模式。确认执行此操作后,应用仍处于全屏模式。

API 级别 24 至 30

如果您的应用以 API 级别 24 至 30 为目标平台,并且未停用多窗口支持,请在分屏模式和自由窗口模式下验证以下行为:

  • 在全屏模式下启动应用,然后通过长按“最近”按钮切换到多窗口模式。确认应用能正常切换。
  • 直接在多窗口模式下启动应用,确认应用能正常启动。您可以按一下“最近”按钮,然后长按应用的名称栏,并将其拖动到屏幕上任一突出显示的区域,从而在多窗口模式下启动应用。
  • 拖动屏幕分隔线,调整应用在分屏模式下的大小。确认应用能正常调整大小且未崩溃,并且必要的界面元素仍然可见。
  • 如果您已指定应用的最小尺寸,请尝试调整应用尺寸,使其低于这些尺寸。确认无法将应用尺寸调整到指定最小尺寸以下。
  • 完成所有测试后,确认应用性能可以接受。例如,确认调整应用尺寸后,更新界面没有长时间的滞后。

API 级别 31 或更高级别

如果您的应用以 API 级别 31 或更高级别为目标平台,并且主 activity 的最小宽度和最小高度没有超过可用显示屏区域的对应尺寸,请针对 API 级别 24 至 30 验证列出的所有行为。

测试核对清单

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

  • 进入和退出多窗口模式。
  • 从您的应用切换至另一个应用,确认应用在非活跃但可见的状态下正常运行。例如,如果您的应用正在播放视频,请验证当用户与另一个应用互动时,视频仍在继续播放。
  • 在分屏模式下,尝试移动屏幕分隔线,放大和缩小您的应用。在左右并排和上下并排配置下,都要尝试这些操作。确认应用不会崩溃,主要功能可见,且调整大小的操作无需过长时间。
  • 快速连续地执行几次调整大小的操作。确认应用不会崩溃或出现内存泄漏。Android Studio 的内存分析器可提供关于应用内存使用情况的信息(详见使用内存分析器查看应用的内存使用情况)。
  • 在多种不同的窗口配置下正常使用应用,确认应用能正常运行。确认文本可读,且界面元素大小正常,不影响互动。

已停用多窗口模式支持

在 API 级别 24 至 30 的平台上,如果您通过设置 android:resizeableActivity="false" 停用了多窗口模式支持,则应在搭载 Android 7.0 至 11 的设备上启动您的应用,并尝试将该应用置于分屏模式和自由窗口模式。确认执行此操作后,应用仍处于全屏模式。

其他资源

如需详细了解 Android 中的多窗口支持,请参阅: