在 Overview 点击应用图标后出现的 Menu 是在 TaskMenuVew 中添加的。
package com.android.quickstep.views;
/**
* Contains options for a recent task when long-pressing its icon.
*/
public class TaskMenuView extends AbstractFloatingView {
/** Note that these will be shown in order from top to bottom, if available for the task. */
public static final TaskSystemShortcut[] MENU_OPTIONS = new TaskSystemShortcut[] {
new TaskSystemShortcut.AppInfo(),
new TaskSystemShortcut.SplitScreen(),
new TaskSystemShortcut.Pin(),
new TaskSystemShortcut.Install(),
};
...
private void addMenuOptions(TaskView taskView) {
...
for (TaskSystemShortcut menuOption : MENU_OPTIONS) {
OnClickListener onClickListener = menuOption.getOnClickListener(mActivity, taskView);
if (onClickListener != null) {
// 设置点击事件
addMenuOption(menuOption, onClickListener);
}
}
}
}
SplitScreen Menu 就是 new TaskSystemShortcut.SplitScreen()
返回的。SplitScreen 类是 TaskSystemShortcut 类的内部类。getOnClickListener()
方法返回 OnClickListener 对象,当点击“Split Screen” Menu 时调用。
返回的 OnClickListener 对象中调用 AMS 的 startActivityManagerFromRecents()
方法,参数 ActivityOption 对象是调用 ActivityOptionsCompat.makeSplitScreenOptions()
创建的。
package com.android.quickstep;
/**
* Represents a system shortcut that can be shown for a recent task.
*/
public class TaskSystemShortcut<T extends SystemShortcut> extends SystemShortcut
public static class SplitScreen extends TaskSystemShortcut {
@Override
public View.OnClickListener getOnClickListener(
BaseDraggingActivity activity, TaskView taskView) {
...
return (v -> {
...
if (ActivityManagerWrapper.getInstance().startActivityFromRecents(taskId,
ActivityOptionsCompat.makeSplitScreenOptions(dockTopOrLeft) {
ISystemUiProxy sysUiProxy = RecentsModel.getInstance(activity).getSystemUiProxy();
try {
sysUiProxy.onSplitScreenInvoked();
} catch (RemoteException e) {
Log.w(TAG, "Failed to notify SysUI of split screen: ", e);
return;
}
...
}});}}
makeSplitScreenOptions()
方法返回以 SplitScreen 模式启动 task 的 ActivityOption 对象。主要是调用 setLaunchWindowingMode()
方法设置了 WindowingMode。
package com.android.systemui.shared.system;
/**
* Wrapper around internal ActivityOptions creation.
*/
public abstract class ActivityOptionsCompat {
/**
* @return ActivityOptions for starting a task in split screen.
*/
public static ActivityOptions makeSplitScreenOptions(boolean dockTopLeft) {
final ActivityOptions options = ActivityOptions.makeBasic();
options.setLaunchWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
options.setSplitScreenCreateMode(dockTopLeft
? SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT
: SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT);
return options;
}}
接下来分析用 WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
调用 startActivityFromRecents()
方法时都有什么流程,怎么启动了分屏。
在最近任务页面,长按 task 后边缘出现的可拖动区域是 DockState 类,内部创建了 5 个静态对象,分别对应上下左右和空。
com.android.systemui.recents.views.DockState
Dock 的显示配置是在 RecentsConfiguration 中定义的。手机纵向时显示 TOP,横向时显示 LEFT。平板纵向时显示 TOP,横向时显示 LEFT 和 RIGHT。RecentsConfiguration 类中 getDockStatesForCurrentOrientation()
方法可以根据设备类型和方向返回相应的 DockState 对象。
com.android.systemui.recents.RecentsConfiguration
拖动事件是用 EventBus 发送的,拖动开始事件是 DragStartEvent,拖动结束事件是 DragEndEvent。