在 Android 7.0 中,引入了一个新的而且非常需要的多任务处理功能 — 多窗口支持。用户可以一次在屏幕上打开两个应用。Android N 添加了对同时显示多个应用窗口的支持。
具体的效果是,在手持设备上,两个应用可以在“分屏”模式中左右并排或上下并排显示。 在电视设备上,应用可以使用“画中画”模式,在用户与另一个应用交互的同时继续播放视频。
在运行 Android 7.0 的手机和平板电脑上,用户可以并排运行两个应用,或者处于分屏模式时一个应用位于另一个应用之上。用户可以通过拖动两个应用之间的分隔线来调整应用。
在 Android TV 设备上,应用可以将自身置于画中画模式,从而让它们可以在用户浏览或与其他应用交互时继续显示内容。
多窗口支持为您提供新的吸引用户方式,特别是在平板电脑和其他更大屏幕的设备上。您甚至可以在您的应用中启用拖放,从而使用户可以方便地将内容拖放到您的应用或从其中拖出内容—这是一个非常好的增强用户体验的方式。
向您的应用添加多窗口支持并配置多窗口显示的处理方式非常简单。例如,您可以指定您的 Activity允许的最小尺寸,从而防止用户将 Activity 调整到该尺寸以下。您还可以为应用停用多窗口显示,这可确保系统将仅以全屏模式显示应用。
多窗口模式不会更改 Activity 生命周期。
在多窗口模式中,在指定时间只有最近与用户交互过的 Activity 为活动状态。 该 Activity 将被视为顶级 Activity。例如,多窗体在上下开了两个应用A和B,从正在和应用A交互,然后点击应用B进行交互,那么应用A就会调用onPause()方法,因为应用A还是处于可见状态。如果再回到应用B,那么应用B顶部的activity也会调用onPause()方法。
注意:如果应用A是在播放视频的话,我们当然希望在和应用B进行交互的时候,应用A的视频一直会在播放,才符合多窗体的设计。那么建议播放视频的 Activity 不要暂停其 onPause() 处理程序中的视频。 应暂停 onStop() 中的视频,并恢复 onStart() 中的视频播放。
用户使用多窗口模式显示应用时,系统将通知 Activity 发生配置变更。该变更与系统通知应用设备从纵向模式切换到横向模式时的 Activity 生命周期影响基本相同,但设备不仅仅是交换尺寸,而是会变更尺寸。 Activity 可以自行处理配置变更,或允许系统销毁 Activity,并以新的尺寸重新创建该 Activity。
如果用户在自行调整activity的窗口大小,系统会通知应用大小在变更,如果activity没来得及处理,系统会在变化的区域使用 windowBackground 属性或默认 windowBackgroundFallback样式属性指定的颜色暂时填充该区域。
可以在清单文件中设置属性,以控制大小和布局。 根 Activity 的属性设置适用于其任务栈中的所有 Activity。 例如,如果根 Activity 已 android:resizeableActivity 设定为 true,则任务栈中的所有 Activity 都将可以调整大小。
在清单的 activity 或 application 节点中设置该属性,启用或禁用多窗口显示:
android:resizeableActivity=["true" | "false"]
说明:如果该属性设置为 true,Activity 将能以分屏和自由形状模式启动。 如果此属性设置为 false,Activity 将不支持多窗口模式。 如果该值为 false,且用户尝试在多窗口模式下启动 Activity,该 Activity 将全屏显示。Android N默认情况下是为true。
对于 Android N,layout节点清单元素支持以下几种属性,这些属性影响 Activity 在多窗口模式中的行为:
android:defaultWidth //以自由形状模式启动时 Activity 的默认宽度。
android:defaultHeight //以自由形状模式启动时 Activity 的默认高度。
android:gravity //以自由形状模式启动时 Activity 的初始位置。
android:minimalHeight/android:minimalWidth //分屏和自由形状模式中 Activity 的最小高度和最小宽度。 如果用户在分屏模式中移动分界线,使 Activity 尺寸低于指定的最小值,系统会将 Activity 裁剪为用户请求的尺寸。
<activity android:name=".MyActivity">
<layout android:defaultHeight="500dp"
android:defaultWidth="600dp"
android:gravity="top|end"
android:minimalHeight="450dp"
android:minimalWidth="300dp" />
activity>
在设备处于多窗口模式中时,某些功能会被禁用或忽略,因为这些功能对与其他 Activity 或应用共享设备屏幕的 Activity 而言没有意义。 此类功能包括:
某些系统 UI 自定义选项将被禁用;例如,在非全屏模式中,应用无法隐藏状态栏。
系统将忽略对 android:screenOrientation 属性所作的更改。
对于应用进入多窗体的时候,系统会给我们怎样的回调呢?Activity 类中添加了新的方法,以支持多窗口显示。
Activity.isInMultiWindowMode() //调用该方法以确认 Activity 是否处于多窗口模式。
Activity.isInPictureInPictureMode() //调用该方法以确认 Activity 是否处于画中画模式。(注:画中画模式是多窗口模式的特例。 如果 myActivity.isInPictureInPictureMode() 返回 true,则 myActivity.isInMultiWindowMode() 也返回 true。)
Activity.onMultiWindowModeChanged() //Activity 进入或退出多窗口模式时系统将调用此方法。 在 Activity 进入多窗口模式时,系统向该方法传递 true 值,在退出多窗口模式时,则传递 false 值。
Activity.onPictureInPictureModeChanged() //Activity 进入或退出画中画模式时系统将调用此方法。 在 Activity 进入画中画模式时,系统向该方法传递 true 值,在退出画中画模式时,则传递 false 值。
注意:在Fragment中也有上面的几个方法。
如需在画中画模式中启动 Activity,请调用新方法 Activity.enterPictureInPictureMode()。 如果设备不支持画中画模式,则此方法无效。
在启动新 Activity 时,用户可以提示系统如果可能,应将新 Activity 显示在当前 Activity 旁边。 要执行此操作,可使用标志 Intent.FLAG_ACTIVITY_LAUNCH_TO_ADJACENT。 传递此标志将请求以下行为:
如果设备处于分屏模式,系统会尝试在启动系统的 Activity 旁创建新 Activity,这样两个 Activity 将共享屏幕。 系统并不一定能实现此操作,但如果可以,系统将使两个 Activity 处于相邻的位置。
如果设备不处于分屏模式,则该标志无效。
如果设备处于自由形状模式,则在启动新 Activity 时,用户可通过调用 ActivityOptions.setLaunchBounds() 指定新 Activity 的尺寸和屏幕位置。 如果设备不处于多窗口模式,则该方法无效。
注:如果您在任务栈中启动 Activity,该 Activity 将替换屏幕上的 Activity,并继承其所有的多窗口属性。 如果要在多窗口模式中以单独的窗口启动新 Activity,则必须在新的任务栈中启动此 Activity。
用户可以在两个 Activity 共享屏幕的同时在这两个 Activity 之间拖放数据 (在此之前,用户只能在一个 Activity 内部拖放数据)。 因此,如果您的应用目前不支持拖放功能,您可以在其中添加此功能。
android.view.DropPermissions
令牌对象,负责指定对接收拖放数据的应用授予的权限。
View.startDragAndDrop()
View.startDrag() 的新别名。要启用跨 Activity 拖放,请传递新标志 View.DRAG_FLAG_GLOBAL。 如需对接收拖放数据的 Activity 授予 URI 权限,可根据情况传递新标志 View.DRAG_FLAG_GLOBAL_URI_READ 或 View.DRAG_FLAG_GLOBAL_URI_WRITE。
View.cancelDragAndDrop()
取消当前正在进行的拖动操作。只能由发起拖动操作的应用调用。
View.updateDragShadow()
替换当前正在进行的拖动操作的拖动阴影。只能由发起拖动操作的应用调用。
Activity.requestDropPermissions()
请求使用 DragEvent 中包含的 ClipData 传递的内容 URI 的权限。
如果应用不是使用 N Preview SDK 构建的或者运行 Android N 的设备上启动应用,用户进行多窗体操作,系统强制进行调整应用大小。除非应用中声明了。
如果您通过设置 android:resizableActivity=”false” 禁用了多窗口支持,则应在运行 Android N 的设备上启动应用,并尝试将应用切换到自由形状和分屏模式。 验证并确保执行此操作后,应用仍保持全屏模式。