1-问题摘要
这次主要解决困扰了我很久的时钟消失问题,大概是去年10月刚开始做EDLA项目的时候,需要定制谷歌桌面,桌面布局大概要改成这样:
时间显示在谷歌搜索框的上方,而安卓原生桌面大概是这样子的
我们开发一开始是使用小部件的方式加载谷歌时钟显示在桌面,而我们知道,桌面显示的任何组件都是以行和列的形式存在的,当时我们想要改时间为2行3列才能达到预期效果,但是奇怪的是2行3列的时间小部件在开机后并没有显示出来,暂时找不到原因只好使用1行3列布局,大概长这样
无论是默认定义2行或者是手动调整到2行,重启后时钟都会消失.
二-解决方法
先贴解决方法吧,原因分析写在后面,想看就看
小部件消失一般是跟谷歌搜索框有关,修改路径为Launcher3目录下的src/com/android/launcher3/model/LoaderCursor.java
找到这个方法
/**
* check & update map of what's occupied; used to discard overlapping/invalid items
*/
protected boolean checkItemPlacement(ItemInfo item) {
int containerIndex = item.screenId;
if (item.container == Favorites.CONTAINER_HOTSEAT) {
final GridOccupancy hotseatOccupancy =
mOccupied.get(Favorites.CONTAINER_HOTSEAT);
if (item.screenId >= mIDP.numDatabaseHotseatIcons) {
Log.e(TAG, "Error loading shortcut " + item
+ " into hotseat position " + item.screenId
+ ", position out of bounds: (0 to " + (mIDP.numDatabaseHotseatIcons - 1)
+ ")");
return false;
}
if (hotseatOccupancy != null) {
if (hotseatOccupancy.cells[(int) item.screenId][0]) {
Log.e(TAG, "Error loading shortcut into hotseat " + item
+ " into position (" + item.screenId + ":" + item.cellX + ","
+ item.cellY + ") already occupied");
return false;
} else {
hotseatOccupancy.cells[item.screenId][0] = true;
return true;
}
} else {
final GridOccupancy occupancy = new GridOccupancy(mIDP.numDatabaseHotseatIcons, 1);
occupancy.cells[item.screenId][0] = true;
mOccupied.put(Favorites.CONTAINER_HOTSEAT, occupancy);
return true;
}
} else if (item.container != Favorites.CONTAINER_DESKTOP) {
// Skip further checking if it is not the hotseat or workspace container
return true;
}
final int countX = mIDP.numColumns;
final int countY = mIDP.numRows;
if (item.container == Favorites.CONTAINER_DESKTOP && item.cellX < 0 || item.cellY < 0
|| item.cellX + item.spanX > countX || item.cellY + item.spanY > countY) {
Log.e(TAG, "Error loading shortcut " + item
+ " into cell (" + containerIndex + "-" + item.screenId + ":"
+ item.cellX + "," + item.cellY
+ ") out of screen bounds ( " + countX + "x" + countY + ")");
return false;
}
if (!mOccupied.containsKey(item.screenId)) {
GridOccupancy screen = new GridOccupancy(countX + 1, countY + 1);
if (item.screenId == Workspace.FIRST_SCREEN_ID && FeatureFlags.QSB_ON_FIRST_SCREEN) {
// Mark the first X columns (X is width of the search container) in the first row as
// occupied (if the feature is enabled) in order to account for the search
// container.
int spanX = mIDP.numSearchContainerColumns;
int spanY = 1;
screen.markCells(0, 0, spanX, spanY, true);
}
mOccupied.put(item.screenId, screen);
}
final GridOccupancy occupancy = mOccupied.get(item.screenId);
// Check if any workspace icons overlap with each other
if (occupancy.isRegionVacant(item.cellX, item.cellY, item.spanX, item.spanY)) {
occupancy.markCells(item, true);
return true;
} else {
Log.e(TAG, "Error loading shortcut " + item
+ " into cell (" + containerIndex + "-" + item.screenId + ":"
+ item.cellX + "," + item.cellX + "," + item.spanX + "," + item.spanY
+ ") already occupied");
return false;
}
}
这个方法用来判断加载的组件相互之间是否存在布局重叠,如果有布局重叠,则不加载相应的组件
这行代码标记了谷歌搜索框的位置,从第1行第一列开始,占据spanX列和spanY行的空间,一般spanX在配置文件里定义为5,spanY为1,所以桌面的第一行基本是谷歌搜索框的天下,解决办法要根据你主布局是否需要搜索框来改:
1.如果你的布局不需要谷歌搜索框,就直接把screen.markCells(0, 0, spanX, spanY, true);给注释掉;
2.需要谷歌搜索框的话,就需要保持你桌面搜索框显示的位置和这里一致,查看src/com/android/launcher3/Workspace.java的bindAndInitFirstWorkspaceScreen()方法,里面定义了谷歌搜索框的位置
比如我这里定义居中的是从第二行第一列开始,占据5列1行空间,所以要把screen.markCells(0, 0, spanX, spanY, true);改为screen.markCells(1, 2, 5, 1, true);
这样改了之后就不会计算出组件布局重叠区域了,可以正常显示衍生到桌面第一行的小部件,不单单是时钟组件.
三-原理分析
首先分析桌面启动加载小部件流程…未完待续