前言
这里说明一下为什么需要再开一篇分屏描述,因为Android11分屏与Android12的分屏的结构体和设计有一定的差异,故此单独一篇来讲述Android12的分屏,并带着项目需求A三分屏定制一起描述讲解
需求描述
基于android12分双屏功能需要完成分屏,并在三个屏幕中可以使用甩屏功能,具体完善功能如下,三个屏幕分别为中控屏,副驾屏与后排屏
分屏
可以分三屏,上新增一个分屏区间
在原有滑动基础上重新设计三屏滑动互动的算法
在对分屏做增加删除和替换时重新设计布局变化
在分屏中长按界面顶部条推拽改变分屏位置
相关变化动画效果待定
甩屏
暂定使用分屏拖拽同样的方案,在滑动一定的区域自动在当前屏幕消失并在其他屏幕中展示
新增屏幕满时的相关对话框和覆盖逻辑
常用缩写
缩写 | 全称 | 描述 |
---|---|---|
ATMS | ActivityTaskManagerService | 界面任务管理服务,用于管理所有界面等生命周期管理,层级布局大小等控制 |
WMS | WindowManagerService | 窗口管理服务,所有界面也都属于窗口管理 |
FW | Famework | 框架,整个andorid系统的框架层 |
图层叠加示意图
图1
图1中展示画面图层结构,以Z轴的方向查看壁纸,桌面以及应用界面等状态栏层级
其中DemoSystemUI负责多个窗口以及分屏层级管理
主要模块交互示意图
图2
图2中展示主要模块和简单的交换关系
DemoLauncher:主要用于桌面展示,显示全部应用菜单等其他工具功能。
DemoSystemUI:主要用于分屏甩屏功能的控制端,并展示状态栏(StatusBar)与底部导航栏(NavigationBar)
Other App:所有app应用,用于界面展示,并可以在分屏框架中体现
System_server: 系统服务,大部分系统功能服务管理实现都在此进程
ActivityTaskManagerService:activity任务管理服务,简称ATMS,用于管理activity界面展示跳转和大小等控制
WindowManagerService:窗口管理服务,用于拖拽时所滑动的区域,状态栏和底部导航栏这些特殊窗口的图层等级,位置与大小控制。
由于分屏相关改动和业务逻辑都在DemoSystemUI里面,故此在这里着重讲解此模块。
细化DemoSystemUI功能
按包功能划分
图3
以上都是按照java包名归类划分功能与职责,黄色部分代表是需要定制修改为三屏的文件,由于demo未完善,其他文件也可能会需要修改,后续持续更新此图
主要分三个部分
DemoSystemUI
分屏拖放
包:com.android.wm.shell.draganddrop
概述:拖拽与放下分屏画面的功能
DragAndDropController:拖放控制,在初始化initialize方法中通过DisplayController.addDisplayWindowListener注册监听Display显示屏变化,当有回调触发onDisplayAdded方法时,通过WindowManager添加一个TYPE_APPLICATION_OVERLAY类型的窗口,内部绑定DragLayout视图,用于监听和拖拽对应的
DragEvent:拖放事件,这里我们使用这个方案来完成分屏的拖拽和甩屏移动效果。详情可以参考:启用拖放 | Views | Android Developers
DragAndDropPolicy:拖放代理,主要是代理DragLayout传递过来的拖放事件并且计算相应的区域,然后给SplitScreenController这个分屏控制类执行对应的滑动效果与布局位置。
DragLayout:拖动布局,主要是接受来自系统反馈的DragEvent事件,并把相应的事件给与代理处理,本身是作为一个视图布局依附在窗口上的。
DropOutlineDrawable:显示分屏即将显示区域,并自带缩放与渐变效果的动画。
图4
基础类
包:com.android.wm.shell.common
概述:一些基础比较单一的功能
SyncTransactionQueue:主要与系统交互提交刷新布局与移动的事务,基本当前设计所有分屏移动与布局的变化都是通过向这个类提交对应的周边数据
TransactionPool:一个提交事务的缓存池,代码上固定4个缓存,用于在频繁提交事务时,可以保持内存平稳,让系统更加稳定。
DisplayController:显示控制,用于监听显示屏的增加删除与变化,这里设计是通过显示的增加来创建对应的DragAndDrop拖放窗口。
DisplayLayout:显示布局,包含Display对象,用于记录显示屏的一些信息
图5
分屏接口控制
包:com.android.wm.shell.splitscreen
概述:用于对分屏做滑动布局等控制
ISplitScreen:提供了一种跨进程的方式,用于管理和控制 Android 设备上的分屏功能。通过定义一系列方法,它允许外部进程启动和退出分屏模式、检查分屏支持和状态、获取分屏舞台信息,并注册和注销分屏模式的监听器。这使得应用程序能够在不同场景下灵活地管理和响应分屏模式的变化。
ISplitScreenListener:该接口用于监听分屏模式下的任务和阶段变化,主要用于系统内部组件之间的通信。
SplitScreen:接口提供了一种标准化的方式来管理和监听 Android 设备上的分屏功能。通过定义明确的常量、注解、内部接口和方法,它确保了分屏操作的类型安全性和可扩展性。应用程序可以通过实现 SplitScreenListener 接口来监听分屏状态的变化,并通过 createExternalInterface 方法获得对外部进程的支持。
MainStage:类负责管理分屏模式下的主舞台。它提供了激活、停用和更新配置的方法,确保主舞台在分屏模式下正确管理和显示任务。通过 WindowContainerTransaction 对象,它可以对任务进行各种操作,如设置边界、窗口模式、启动根任务和重新排列任务。
SideStage:类主要用于管理分屏模式下的侧边舞台,提供了添加、移除和管理任务的功能。通过与 ShellTaskOrganizer、WindowContainerTransaction 等类的协作,确保任务在侧边舞台上的正确显示和操作。
SplitScreenTransitions:负责管理分屏模式下过渡动画的类。它主要用于处理分屏模式中的各种动画效果,例如任务进入、退出、拖动分隔条等。
StageTaskListener:负责管理和响应分屏模式下任务的变化,确保任务之间的协调和同步。通过实现 ShellTaskOrganizer.TaskListener 接口,它能够监听并响应任务生命周期的关键事件,从而保证分屏体验的流畅性和一致性。MainStage和SideStage都是继承该类。
SplitScreenController:它不仅提供了丰富的 API 来控制和管理分屏模式,还支持跨进程通信和拖放操作,确保了分屏模式的高效和灵活使用。通过 StageCoordinator 和其他辅助类的配合,SplitScreenController 能够有效地协调多个任务在分屏环境中的运行,为用户提供流畅的多任务体验。
StageCoordinator:一个协调器,布局,事件,动画和调试等操作的各方面调度工作。
ps:在StageCoordinator 内部会新增一个SideStage用于表示第三个分屏
图6
分屏界面展示
包:com.android.wm.shell.common.split
概述:用于对分屏做滑动布局等显示与实际计算
DividerHandleView:是一个自定义的 View
类,主要用于在分屏或多任务界面中作为分隔条的拖动手柄。这个手柄允许用户通过触摸和拖动来调整分屏的大小。
DividerView:是一个分割线视图,用于响应对应的触摸事件,其中GestureDetector手势识别针对双击触发分屏互换逻辑
SplitLayout:负责处理屏幕上的多任务分屏布局。它主要记录和处理分屏的布局信息,包括计算分屏边界、处理分屏位置变化等。该类还处理与虚拟键盘(IME)相关的布局调整,确保在虚拟键盘显示时分屏布局的正确性。
SplitWindowManager:是一个用于管理分屏窗口的类,主要负责处理分屏窗口的创建、管理和布局。它通常与 SplitLayout 一起使用,以确保分屏布局的正确性和用户体验。以下是对 SplitWindowManager 的详细概述,包括其主要功能、属性和方法。
图7
初始化构建
包:com.android.wm.shell
概述:初始化与注册等相关类
ShellInit:初始化接口
ShellInitImpl: 是一个实现 ShellInit 接口的类,负责初始化 Android 系统中的多个核心组件和服务。这些组件包括虚拟键盘控制器、拖放控制器、任务组织器、气泡控制器、分屏控制器、全屏任务监听器、过渡动画管理器和启动窗口控制器等。以下是 ShellInitImpl 的详细概述,包括其主要功能、属性和方法。
ShellTaskOrganizer:一个任务组织者,用于与系统注册监听task的变化,例如新增,消失和参数有变化。
ps:我们这里只提供分屏相关功能其他功能代码会删除。
图8
Frameworks jar
窗口接口
包:android.window
概述:窗口相关布局滑动事务接口
WindowOrganizer:窗口组织者,监听窗口等变化
TaskOrganizer:任务组织者,监听任务等变化
WindowContainerTransaction:窗口内容事务包
视图接口
包:android.view
概述:窗口管理与视图相关布局滑动事务接口
WindowManager:窗口管理,用于添加删除和更新窗口
DragEvent:拖放的事件,里面包含action,移动信息和clipdata数据,内部可以有文字uil,intent等信息
SurfaceControl:surface 绘制控制对象
Frameworks service
窗口服务
包:com.android.server.wm
概述:系统内部整个窗口体系框架的实现层
ActivityTaskManagerService:负责管理应用程序的任务和活动(Activity)。它处理应用程序的启动、切换、多任务管理、分屏模式等功能。
RootWindowContainer:是 Android 系统中用于管理所有窗口和任务的顶层容器。它是 ActivityTaskManagerService
的一部分,负责管理所有显示在屏幕上的任务和窗口。
DisplayContent:是 Android 系统中用于管理特定显示设备上的内容的类。每个显示设备(如主屏幕、外部显示器等)都有一个对应的 DisplayContent
实例,负责管理该显示设备上的任务和窗口。以下是 DisplayContent
的详细概述,包括其主要功能、属性和方法。
TaskDisplayArea:是 Android 系统中用于管理特定显示区域内的任务和窗口的类。每个 DisplayContent
实例可以包含多个 TaskDisplayArea
,每个 TaskDisplayArea
负责管理特定区域内的任务和窗口布局。
Task:管理任务内部所有活动(Activiy),处理任务的创建、销毁、显示和隐藏,管理任务的堆栈和层次结构。
ActivityRecord:对应活动(activity)的生命周期管理与配置变化
WindowOrganizerController:窗口组织者控制,刷新分屏画面同步事务,监听屏幕状态
TaskOrganizerController:任务组织者控制, 监听和创建task,和launchTask设置。
BLASTSyncEngine:一个对SurfaceControl.Transaction事务刷新的同步引擎
图9
图9中DisplayContent代表每一个屏幕,我们当前设计是有三个屏幕,故此会有三个DisplayContent。下面TaskDisplayArea ,Task,ActivityRecord都是一对多的关系。
关于Organizer这个组织者的概念,我这边理解有三个方面,第一个是监听屏幕,DisplayArea,Task等变化, 第二个可以主动创建多屏类型的Task,DisplayArea,第三个可以通过WindowContainerTransaction 和SurfaceControl.Transaction 移动和改变DisplayArea和Task位置与大小变化。
图10
启动时序
DemoSystemUI常驻进程与开机自启功能:android:persistent=“true”
图11
初始化主要是构造三个类,分别用于分屏控制(SplitScreenController ),拖放控制(DragAndDropController)以及注册监听task等系统信息(ShellTaskOrganizer)
总结修改项方案
1 需要加一个三个点的选中图标,用于单选选择分屏菜单,长按拖放分屏来移动位置, 三个点是新增一个图层还是依附在现有的图层待demo开发过程中考虑
2 在DragAndDrop这个功能里分离三个分屏概念,需要新增一个区域,并在拖拽滑动中重新改写计算方案。
3 在SplitLayout这个布局内部也需要心中第三个分屏概念,也需要改写对应的判断和计算方案。
4 在StageCoordinator 新增一个SideStage,并在其内部相关位置都添加上对应的调用。