上一篇文章(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