上一篇文章(AOSP6.0.1 launcher3入门篇—解析launcher.java文件)描述了launcher3的加载过程,本篇文章记录hotseat停靠方向和位置、隐藏页指示器、Folder大小等。
首先介绍构造函数:
找到public DeviceProfile(Context context, InvariantDeviceProfile inv,
Point minSize, Point maxSize,
int width, int height, boolean isLandscape)
this.inv = inv;
传入InvariantDeviceProfile实例对象,InvariantDeviceProfile类负责hotseat的停靠方向,allapps按键进入cellLayout的布局设置,包括指定设备型号的app摆放形式(行、列设置)和icon大小,在文章最后对InvariantDeviceProfile类进行分析
this.isLandscape = isLandscape;
如果传入的是true桌面为横屏,false桌面为竖屏
isTablet = res.getBoolean(R.bool.is_tablet);
isLargeTablet = res.getBoolean(R.bool.is_large_tablet);
这里调用的packages/apps/Launcher3/res/values/config.xml ,tablet和large_tablet默认为false
transposeLayoutWithOrientation =
res.getBoolean(R.bool.hotseat_transpose_layout_with_orientation);
这里也是调用config.xml,<bool name="hotseat_transpose_layout_with_orientation">true</bool>
允许hotseat设置停靠方向和停靠位置(比如放置在屏幕正中心位置),如果为false在横屏模式下无效
edgeMarginPx = res.getDimensionPixelSize(R.dimen.dynamic_grid_edge_margin);
desiredWorkspaceLeftRightMarginPx = 2 * edgeMarginPx;
pageIndicatorHeightPx =
res.getDimensionPixelSize(R.dimen.dynamic_grid_page_indicator_height);
defaultPageSpacingPx =
res.getDimensionPixelSize(R.dimen.dynamic_grid_workspace_page_spacing);
overviewModeMinIconZoneHeightPx =
res.getDimensionPixelSize(R.dimen.dynamic_grid_overview_min_icon_zone_height);
overviewModeMaxIconZoneHeightPx =
res.getDimensionPixelSize(R.dimen.dynamic_grid_overview_max_icon_zone_height);
overviewModeBarItemWidthPx =
res.getDimensionPixelSize(R.dimen.dynamic_grid_overview_bar_item_width);
overviewModeBarSpacerWidthPx =
res.getDimensionPixelSize(R.dimen.dynamic_grid_overview_bar_spacer_width);
overviewModeIconZoneRatio =
res.getInteger(R.integer.config_dynamic_grid_overview_icon_zone_percentage) / 100f;
iconDrawablePaddingOriginalPx =
res.getDimensionPixelSize(R.dimen.dynamic_grid_icon_drawable_padding);
这里调用的packages/apps/Launcher3/res/values/dimens.xml
if (isLandscape) {
availableWidthPx = maxSize.x;
availableHeightPx = minSize.y;
如果是横屏模式,采用x轴最大值,y轴最小值(比如比例为800*600)
} else {
availableWidthPx = minSize.x;
availableHeightPx = maxSize.y;
如果是竖屏模式,采用x轴最小值,y轴最大值(比如比例为600*800)
}
private void updateAvailableDimensions(DisplayMetrics dm, Resources res)函数:
float scale = 1f;
默认比例
int drawablePadding = iconDrawablePaddingOriginalPx;
当folder展开时,folder的高度为iconSizePx + drawablePadding + fm上限得到folder的实际高度
updateIconSize(1f, drawablePadding, res, dm);
按实际比例计算出文件夹范围、hotseat范围
Rect workspacePadding = getWorkspacePadding(false /* isLayoutRtl */);
返回workspace空间,workspace是PageView类型,
PageView大小可以在public void layout(Launcher launcher)中设置
private void updateIconSize(float scale, int drawablePadding, Resources res,
DisplayMetrics dm)函数:
hotseatBarHeightPx = iconSizePx + 4 * edgeMarginPx;
不修改xml的情况下,修改hotseatBarHeightPx值可以改变Hotseat空间大小,达到
Hotseat放置屏幕中间位置效果
hotseatBarHeightPx = (availableWidthPx + iconSizePx + 6 * edgeMarginPx);
这个是修改后,hotseat空间范围变大,看起来像放置到屏幕中间,按钮触发事件的范围也会变大
private void computeAllAppsButtonSize(Context context)函数:
float padding = res.getInteger(R.integer.config_allAppsButtonPaddingPercent) / 100f;
修改hotseat空间内所有app(不包括allapps按钮进入的CellLayout内app)的占用比例
xml文件所在位置/res/values/config.xml
public void layout(Launcher launcher)函数:
PagedView workspace = (PagedView) launcher.findViewById(R.id.workspace);
lp = (FrameLayout.LayoutParams) workspace.getLayoutParams();
lp.gravity = Gravity.CENTER;
Rect padding = getWorkspacePadding(isLayoutRtl);
workspace.setLayoutParams(lp);
workspace.setPadding(padding.left, padding.top, padding.right, padding.bottom);
workspace.setPageSpacing(getWorkspacePageSpacing(isLayoutRtl));
这段是创建workspace的代码,xml位置在res/下,如果是竖屏调用layout-port/launcher.xml,
横屏调用layout-land/launcher.xml,修改xml可以实现主界面空白的效果
<include layout="@layout/hotseat"
android:id="@+id/hotseat"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:visibility="gone" />
在hotseat字段中增加“android:visibility="gone"”即可隐藏hotseat布局
显示空白主界面方法:
hotseat字段增加“android:visibility="gone"”
<com.android.launcher3.Workspace
android:id="@+id/workspace"
android:layout_width="match_parent"
android:layout_height="match_parent"
- launcher:pageIndicator="@+id/page_indicator"
launcher:defaultScreen="@integer/config_workspaceDefaultScreen">
</com.android.launcher3.Workspace>
workspace字段去掉“launcher:pageIndicator="@+id/page_indicator"”,不加载指示器
<com.android.launcher3.FocusIndicatorView
android:id="@+id/focus_indicator"
android:layout_width="0dp"
android:layout_height="0dp" />
FocusIndicatorView字段宽和高改为0dp,在allapps进入的CellLayout布局中(二级桌面)长按app会显示FocusIndicatorView视图
page_indicator字段增加“android:visibility="gone"”,不显示页指示器
下面回到代码中:
如果想在空白桌面中显示所有app是可以实现的,只是目前使用的方式不太正确,按返回键会显示出hotseat布局
从// Layout the hotseat
/*View hotseat = launcher.findViewById(R.id.hotseat);
开始注释一直到 }*/ // Layout the Overview Mode上面的最后一个括号
增加下面一段代码
View allapps = launcher.findViewById(R.id.apps_view);
lp = (FrameLayout.LayoutParams) allapps.getLayoutParams();
lp.gravity = Gravity.CENTER;
allapps.setLayoutParams(lp);
allapps.setPadding(padding.left, padding.top, padding.right, padding.bottom);
启动手机系统后即可看到allapps进入的CellLayout布局和app,这种方式不太好,继续探索新的方式...
下面说下hotseat停靠方向的修改:
进入InvariantDeviceProfile.java文件:
进入InvariantDeviceProfile(Context context)函数:
找到portraitProfile = new DeviceProfile(context, this, smallestSize,largestSize,
largeSide , smallSide, /*false*/false /* isLandscape */);
修改false为true,参考下面
portraitProfile = new DeviceProfile(context, this, smallestSize,largestSize,
largeSide , smallSide,true );
这是竖屏模式下,hotseat布局右方停靠方式
landscapeProfile = new DeviceProfile(context, this, smallestSize,largestSize,
largeSide, smallSide, false);
横屏模式下,true改为false