AndroidQ SearchLauncher布局Launcher

 

1.Launcher界面简介

2.Launcher初始化网格

3.Launcher:defaultLayoutId加载的是default_workspace_5x5,还是partner_default_layout.xml

4.如何客制化default_desktop_grid_name

 

一 .Launcher界面包含Google Search(这是个伪widget),Workspace,Hotseat,Folders。

二  Launcher初始化网格代码:

packages/apps/Launcher3/src/com/android/launcher3/InvariantDeviceProfile.java

packages/apps/Launcher3/res/xml/device_profiles.xml

packages\apps\Launcher3\src\com\sprd\ext\grid\DesktopGridModel.java

    /** 1.gridName值是从DesktopGridModel.java中获得,
      * mDefaultGridName = context.getString(R.string.default_desktop_grid_name);
      * 2.我们如果需要使用已经存在的grid-option,客制化Launcher几行几列,
      * 可以直接修改该值:default_desktop_grid_name
      * 例如:<string name="default_desktop_grid_name" translatable="false">"6_by_5"</string>  	  
    */		
private String initGrid(Context context, String gridName) {
        Log.e("kl", "initGrid **1");
        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        Display display = wm.getDefaultDisplay();
        DisplayMetrics dm = new DisplayMetrics();
        display.getMetrics(dm);

        Point smallestSize = new Point();
        Point largestSize = new Point();
        display.getCurrentSizeRange(smallestSize, largestSize);
        /** 1.getPredefinedDeviceProfiles函数中会加载
          * device_profiles.xml文件,该函数中真正对定义了我们的workspace风格,
          * 包含3x3,4x4,5x5,defaultLayoutId 等重要信息。 
          * 最后会通过参数gridName 过滤出我们项目所要用的。 	  
        */	
        ArrayList<DisplayOption> allOptions = getPredefinedDeviceProfiles(context, gridName);
        // This guarantees that width < height
        float minWidthDps = Utilities.dpiFromPx(Math.min(smallestSize.x, smallestSize.y), dm);
        float minHeightDps = Utilities.dpiFromPx(Math.min(largestSize.x, largestSize.y), dm);
        // Sort the profiles based on the closeness to the device size
        Collections.sort(allOptions, (a, b) ->
                Float.compare(dist(minWidthDps, minHeightDps, a.minWidthDps, a.minHeightDps),
                        dist(minWidthDps, minHeightDps, b.minWidthDps, b.minHeightDps)));
        DisplayOption interpolatedDisplayOption =
                invDistWeightedInterpolate(minWidthDps,  minHeightDps, allOptions);

        GridOption closestProfile = allOptions.get(0).grid;
        numRows = closestProfile.numRows;
        numColumns = closestProfile.numColumns;
        numHotseatIcons = closestProfile.numHotseatIcons;
        defaultLayoutId = closestProfile.defaultLayoutId;
        demoModeLayoutId = closestProfile.demoModeLayoutId;
        numFolderRows = closestProfile.numFolderRows;
        numFolderColumns = closestProfile.numFolderColumns;
        mExtraAttrs = closestProfile.extraAttrs;

        if (!closestProfile.name.equals(gridName)) {
            Utilities.getPrefs(context).edit()
                    .putString(mIdpGridKey, closestProfile.name).apply();
        }
        if (mMonitor.getSRController() != null) {
            mMonitor.getSRController().saveGridNameIntoStorage(context, closestProfile.name);
        }

        iconSize = interpolatedDisplayOption.iconSize;
        iconShapePath = getIconShapePath(context);
        landscapeIconSize = interpolatedDisplayOption.landscapeIconSize;
        iconBitmapSize = ResourceUtils.pxFromDp(iconSize, dm);
        iconTextSize = interpolatedDisplayOption.iconTextSize;
        fillResIconDpi = getLauncherIconDensity(iconBitmapSize);

        //这个地方可能修改我们的几行几列...需要自己看下自己的代码。	
        applyPartnerDeviceProfileOverrides(context, dm);

        Point realSize = new Point();
        display.getRealSize(realSize);
        // The real size never changes. smallSide and largeSide will remain the
        // same in any orientation.
        int smallSide = Math.min(realSize.x, realSize.y);
        int largeSide = Math.max(realSize.x, realSize.y);

        landscapeProfile = new DeviceProfile(context, this, smallestSize, largestSize,
                largeSide, smallSide, true /* isLandscape */, false /* isMultiWindowMode */);
        portraitProfile = new DeviceProfile(context, this, smallestSize, largestSize,
                smallSide, largeSide, false /* isLandscape */, false /* isMultiWindowMode */);

        FolderIconController fic = mMonitor.getFolderIconController();
        if (fic != null) {
            fic.backupOriginalFolderRowAndColumns(numFolderRows, numFolderColumns);
            fic.updateFolderRowAndColumns(this);
        }

        // We need to ensure that there is enough extra space in the wallpaper
        // for the intended parallax effects
        if (context.getResources().getConfiguration().smallestScreenWidthDp >= 720) {
            defaultWallpaperSize = new Point(
                    (int) (largeSide * wallpaperTravelToScreenWidthRatio(largeSide, smallSide)),
                    largeSide);
        } else {
            defaultWallpaperSize = new Point(Math.max(smallSide * 2, largeSide), largeSide);
        }

        ComponentName cn = new ComponentName(context.getPackageName(), getClass().getName());
        defaultWidgetPadding = AppWidgetHostView.getDefaultPaddingForWidget(context, cn, null);

        mDisplayOptionName = interpolatedDisplayOption.name;
        mGridName = closestProfile.name;
		Log.d("kl","initGrid closestProfile.name"+mGridName);
        return closestProfile.name;
    }

三  .Launcher:defaultLayoutId加载的是default_workspace_5x5,还是partner_default_layout.xml

packages\apps\Launcher3\NativeLauncherLayout\res\xml\partner_default_layout.xml

packages/apps/Launcher3/src/com/android/launcher3/Partner.java

如果从上面的代码来看,最后调用的是device_profiles.xml来加载布局文件。

    <grid-option
        launcher:name="3_by_3"
        launcher:numRows="3"
        launcher:numColumns="3"
        launcher:numFolderRows="2"
        launcher:numFolderColumns="3"
        launcher:numHotseatIcons="3"
        <!-- Launcher界面缺省定义的hotseat,icon,folders,widget 都在这里面定义-->
        launcher:defaultLayoutId="@xml/default_workspace_3x3" >

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

        <display-option
            launcher:name="Shorter Stubby"
            launcher:minWidthDps="255"
            launcher:minHeightDps="400"
            launcher:iconImageSize="48"
            launcher:iconTextSize="13.0"
            launcher:canBeDefault="true" />

    </grid-option>

我的项目最后调用的却是partner_default_layout.xml,这是为什么?

还记得上面代码中initGrid函数 函数中调用了applyPartnerDeviceProfileOverrides方法,该方法是这样的:

private static final String
            ACTION_PARTNER_CUSTOMIZATION = "com.android.launcher3.action.PARTNER_CUSTOMIZATION";
private void applyPartnerDeviceProfileOverrides(Context context, DisplayMetrics dm) {
    //Partner.get()会去做什么?它会去寻找系统中匹配的apk		
     Partner p = Partner.get(context.getPackageManager());
     if (p != null) {
         p.applyInvariantDeviceProfileOverrides(this, dm);
      }
}

/**
  * Find and return partner details, or {@code null} if none exists.
*/
public static synchronized Partner get(PackageManager pm) {
    Log.e("kl", "Partner findSystemApk from action  **1");		
     if (!sSearched) {
         Pair<String, Resources> apkInfo = Utilities.findSystemApk(ACTION_PARTNER_CUSTOMIZATION, pm);
         if (apkInfo != null) {
             sPartner = new Partner(apkInfo.first, apkInfo.second);
         }
         sSearched = true;
    }
    return sPartner;
}

最后匹配到的就是:

packages\apps\Launcher3\NativeLauncherLayout\AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2019 Unisoc Inc. All Rights Reserved. -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.unisoc.launcher.customization">
    <application android:label="@string/app_label">
        <!-- This isn't a real receiver, it's only used as a marker interface. -->
        <receiver android:name=".LauncherCustomizationReceiver">
            <intent-filter>
                <action android:name="com.android.launcher3.action.PARTNER_CUSTOMIZATION" />
            </intent-filter>
        </receiver>
    </application>
</manifest>

NativeLauncherLayout是一个单独的模块,在该模块下就定义了:

packages\apps\Launcher3\NativeLauncherLayout\res\xml\partner_default_layout.xml

我们在继续看下面的代码:

packages\apps\Launcher3\src\com\android\launcher3\LoaderTask.java

packages\apps\Launcher3\src\com\android\launcher3\LauncherProvider.java

在Launcher加载的时候,会执行到LoaderTask.java文件中的loadWorkspace()函数。

在loadWorkspace函数中会调用如下代码:

   LogUtils.d(TAG, "loadWorkspace: loading default favorites");
   LauncherSettings.Settings.call(contentResolver,
     LauncherSettings.Settings.METHOD_LOAD_DEFAULT_FAVORITES);

LauncherSettings.Settings.METHOD_LOAD_DEFAULT_FAVORITES又做了什么呢?

case LauncherSettings.Settings.METHOD_LOAD_DEFAULT_FAVORITES: {
    loadDefaultFavoritesIfNecessary();
    return null;
}

synchronized private void loadDefaultFavoritesIfNecessary() {
    if (getFlagEmptyDbCreated(getContext(), mOpenHelper.getDatabaseName())) {
        Log.d("kl", "loading default workspace");

      AppWidgetHost widgetHost = mOpenHelper.newLauncherWidgetHost();
      AutoInstallsLayout loader = createWorkspaceLoaderFromAppRestriction(widgetHost);
      if (loader == null) {
         Log.e("kl", "loadDefaultFavoritesIfNecessary  **1");	
        loader = AutoInstallsLayout.get(getContext(), widgetHost, mOpenHelper);
      }
      if (loader == null) {
           final Partner partner = Partner.get(getContext().getPackageManager());
           if (partner != null && partner.hasDefaultLayout()) {
               final Resources partnerRes = partner.getResources();
               //这里会去Partner文件中获取RES_DEFAULT_LAYOUT
               //而RES_DEFAULT_LAYOUT就是RES_DEFAULT_LAYOUT = "partner_default_layout";
               int workspaceResId = partnerRes.getIdentifier(Partner.RES_DEFAULT_LAYOUT,
                            "xml", partner.getPackageName());
               if (workspaceResId != 0) {
                   loader = new DefaultLayoutParser(getContext(), widgetHost,
                        mOpenHelper, partnerRes, workspaceResId);
                   Log.e("kl", "workspaceResId  **1");								
               }
           }
      }

      .........
    }

四  项目中用的是google的SearchLauncher,但是从Android.mk脚本看,大多数代码都是用到Launcher3的代码。

如果要overlay 客制化某些属性值的话,应该如何客制化?

就拿客制化workspace是用4x4,还是5x5来说,要定制的话,按正常情况下直接overlay下面路径就行,

packages\apps\Launcher3\res\values\config_ext.xml

<string name="default_desktop_grid_name" translatable="false">"6_by_5"</string>

测试了下,发现没有起效果,那需要如何做?

正确的做法是要像我下面这样overlay才有效果:

这里直接写下overlay的路径,一看就明白了,

mocor_AndroidQ\zrevo\e64_xx16-ruiou\overlay\current\vendor\google\apps\SearchLauncher\res\values\config_ext.xml

 

 

 

 

 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值