Android Launcher如何选择默认layoutId?

思考: 接上一篇,在Launcher初始化默认桌面widget的时候,需要选择默认defaultLayoutId,接下来需要弄清楚,默认layout是怎么来的。


前面分析过,defaultLayoutId来自InvariantDeviceProfile的初始化过程
InvariantDeviceProfile.java

    private InvariantDeviceProfile(Context context) {
        String gridName = getCurrentGridName(context);
        String newGridName = initGrid(context, gridName);
        ...
    }
private String initGrid(Context context, String gridName) {
	DefaultDisplay.Info displayInfo = DefaultDisplay.INSTANCE.get(context).getInfo();
	ArrayList<DisplayOption> allOptions = getPredefinedDeviceProfiles(context, gridName);
	DisplayOption displayOption = invDistWeightedInterpolate(displayInfo, allOptions);
	initGrid(context, displayInfo, displayOption);
	return displayOption.grid.name;
}
---
private void initGrid(
   Context context, DefaultDisplay.Info displayInfo, DisplayOption displayOption) {
        GridOption closestProfile = displayOption.grid;
        numRows = closestProfile.numRows;
        numColumns = closestProfile.numColumns;
        numHotseatIcons = closestProfile.numHotseatIcons;
        dbFile = closestProfile.dbFile;
        defaultLayoutId = closestProfile.defaultLayoutId;
        ...
    }

getPredefinedDeviceProfiles获取系统所有的DisplayOption,然后invDistWeightedInterpolate根据系统的尺寸,匹配最接近的DisplayOption
getPredefinedDeviceProfiles的过程中,加载的是R.xml.device_profiles

    <grid-option
        launcher:name="4_by_4"
        launcher:numRows="5"
        launcher:numColumns="4"
        launcher:numFolderRows="4"
        launcher:numFolderColumns="4"
        launcher:numHotseatIcons="4"
        launcher:dbFile="launcher_4_by_4.db"
        launcher:defaultLayoutId="@xml/default_workspace_4x4" >

        <display-option
            launcher:name="Short Stubby"
            launcher:minWidthDps="275"
            launcher:minHeightDps="420"
            launcher:iconImageSize="48"
            launcher:iconTextSize="13.0"
            launcher:canBeDefault="true" />

		...

其中定义了好多grid-option,每个grid-option内部包含几个display-option
包含桌面显示多少行,多少列,数据库名称,默认布局id,最大最小宽高,图标大小这些属性,
接下来就是匹配最佳的过程

DisplayOption displayOption = invDistWeightedInterpolate(displayInfo, allOptions);
---
@VisibleForTesting
static DisplayOption invDistWeightedInterpolate(
        DefaultDisplay.Info displayInfo, ArrayList<DisplayOption> points) {
    Point smallestSize = new Point(displayInfo.smallestSize);
    Point largestSize = new Point(displayInfo.largestSize);

    float width = Utilities.dpiFromPx(Math.min(smallestSize.x, smallestSize.y),
            displayInfo.metrics);
    float height = Utilities.dpiFromPx(Math.min(largestSize.x, largestSize.y),
            displayInfo.metrics);

    Collections.sort(points, (a, b) ->
            Float.compare(dist(width, height, a.minWidthDps, a.minHeightDps),
                    dist(width, height, b.minWidthDps, b.minHeightDps)));

    GridOption closestOption = points.get(0).grid;
    float weights = 0;

    DisplayOption p = points.get(0);
    if (dist(width, height, p.minWidthDps, p.minHeightDps) == 0) {
        return p;
    }

    DisplayOption out = new DisplayOption(closestOption);
    for (int i = 0; i < points.size() && i < KNEARESTNEIGHBOR; ++i) {
        p = points.get(i);
        float w = weight(width, height, p.minWidthDps, p.minHeightDps, WEIGHT_POWER);
        weights += w;
        out.add(new DisplayOption().add(p).multiply(w));
    }
    return out.multiply(1.0f / weights);
}

这里传入的参数,第一个是系统当前显示信息,包含了宽高等属性,我们当前系统的显示屏宽高为600*1024,
根据系统宽高,使用数学公式,计算平方根,根据平方根大小对集合排序。

    Collections.sort(points, (a, b) ->
            Float.compare(dist(width, height, a.minWidthDps, a.minHeightDps),
                    dist(width, height, b.minWidthDps, b.minHeightDps)));

    private static float dist(float x0, float y0, float x1, float y1) {
        return (float) Math.hypot(x1 - x0, y1 - y0);
    }

排完序,还不是直接取最接近的值,而是对集合里前三名进行权重计算,使iconsize,iconTextSize属性取最适合的值。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值