Launcher8.0启动流程的第四步,生成桌面分布局。将UI布局的各个模块,进行基本创建,定义和绑定操作事件等。
在oncreate里面就是一个方法:setupViews()
主要涉及的模块是DragLayer、Workspace、Qsb、Hotseat、OverviewPanel、AppsView、WidgetsView、DropTargetBar。 这几乎涵盖了桌面能够显示的所有UI。
其源码如下:
private void setupViews() {
//第一小步
mDragLayer = (DragLayer) findViewById(R.id.drag_layer);
mFocusHandler = mDragLayer.getFocusIndicatorHelper();
mWorkspace = (Workspace) mDragLayer.findViewById(R.id.workspace);
mQsbContainer = mDragLayer.findViewById(mDeviceProfile.isVerticalBarLayout()
? R.id.workspace_blocked_row : R.id.qsb_container);
mLauncherView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
mDragLayer.setup(this, mDragController, mAllAppsController);
mHotseat = (Hotseat) findViewById(R.id.hotseat);
if (mHotseat != null) {
mHotseat.setOnLongClickListener(this);
}
//第二小步
setupOverviewPanel();
//第三小步
mWorkspace.setHapticFeedbackEnabled(false);
mWorkspace.setOnLongClickListener(this);
mWorkspace.setup(mDragController);
mWorkspace.lockWallpaperToDefaultPage();
mWorkspace.bindAndInitFirstWorkspaceScreen(null /* recycled qsb */);
mDragController.addDragListener(mWorkspace);
mDropTargetBar = (DropTargetBar) mDragLayer.findViewById(R.id.drop_target_bar);
mAppsView = (AllAppsContainerView) findViewById(R.id.apps_view);
mWidgetsView = (WidgetsContainerView) findViewById(R.id.widgets_view);
if (mLauncherCallbacks != null && mLauncherCallbacks.getAllAppsSearchBarController() != null) {
AppsView.setSearchBarController(mLauncherCallbacks.getAllAppsSearchBarController());
} else {
mAppsView.setSearchBarController(new DefaultAppSearchController());
}
mDragController.setMoveTarget(mWorkspace);
mDragController.addDropTarget(mWorkspace);
mDropTargetBar.setup(mDragController);
if (FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP) {
mAllAppsController.setupViews(mAppsView, mHotseat, mWorkspace);
}
}
为了便于记忆,将setupView()方法分为3步。其中最复杂的setupOverviewPanel();
为第2步,这个方法之前为第1步,在此方法之后的行为为第3步。
那么第1小步的代码依次出来分析:
mDragLayer = (DragLayer) findViewById(R.id.drag_layer);
//首先setupview()我们需要记住,setupview()是被onCreate直接调用,也就是说setupview()方法是在Launcher类中。这里对各个UI的创建是通过读取res里面的布局文件。
mFocusHandler = mDragLayer.getFocusIndicatorHelper();
//从布局中获取了Draglayer,并获取了FocusIndicatorHelper。FocusIndicatorHelper是用于处理focus的类。
//android里面的focus,是指UI层面,当前所处理的对象。一般不会被感知到,也不用处理focus。在正常使用过程中,能让我们感知到focus的是edittext(输入框)。当前焦点在输入框时,输入框会有光标,能让我们输入。其实我们点击任何一个组件时,都会有焦点锁定到该组件上。这样我们就能理解为什么focus我们放到负责事件处理的Draglayer里面了。
//Focushelper处理focus是在特定场景下,使对应focus能被用户感知。特定场景是蓝牙外设。
//例如Launcher有代码“favorite.setOnFocusChangeListener(mFocusHandler);”
//Favaorite是桌面的快捷方式。在实际操作中,用实体按键来选择应用,被选择的应用会有灰色框表示选中该快捷方式。
mWorkspace = (Workspace) mDragLayer.findViewById(R.id.workspace);
//创建workspace的对象。桌面放图标的地方由Workspace和hotseat两部分组成。我们将hotseat称作快捷栏,它在屏幕下方,用于放一些不随“页面”滑动而变化的固定图标,“页面”就叫做workspace。
//Workspace父类是PagedView是多个可以滑动的页面组成,PagedView父类是ViewGroup,PagedView的子类是workspace和FolderPagedView。即,Launcher利用ViewGroup做了一套放置图标且可以通过滑动改变当前展示页的类。这个类我们用在了桌面上和文件夹中。
mQsbContainer = mDragLayer.findViewById(mDeviceProfile.isVerticalBarLayout()
? R.id.workspace_blocked_row : R.id.qsb_container);
//创建完workspace后,再创建了google搜索栏。我们知道原则上,图标和widget都是用户爱怎么设就怎么设。但Launcher提供一个不对用户开放的开关,默认是有一个不可移动不可删除的google搜索栏在第一页的桌面上。 这个设定充分证明了,android果然是google开发的。
mLauncherView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
//对SystemUi进行了基本设定,是通过Flag来进行控制。关于Flag有很多
比如,根据当前应用是否全屏,会影响到状态栏是否隐藏。
比如,虚拟按键是否显示,以及其颜色。8.0平台已经支持非实体的“back home recent”按键
后面运行时Launcher也会对SystemUi进行一些简单的设定。主要是显示与否,以及显示的颜色是深色或浅色。
mDragLayer.setup(this, mDragController, mAllAppsController);
//把DragLayer和 mDragController以及 mAllAppsController绑定到一起。这样点击模块就完成了框架层面的搭建。
mHotseat = (Hotseat) findViewById(R.id.hotseat);
//最后setupview()再把hotseat也创建一个对象,这样最基本对象就都准备好了。
if (mHotseat != null) {
mHotseat.setOnLongClickListener(this);
}
以上就是第一小步的内容。