invDistWeightedInterpolate
调用这个方法时传进去的参数是当前手机真实的宽和高,以及经过排序后得到的与目标匹配度由高到低的profiles集合。具体的操作在代码中进行了注解,其实,很多手机型号一致的,计算的时候不算多,有些许差别,计算出来的偏差值也不多,所以这个偏差值纠正就分析到这里。
static DisplayOption invDistWeightedInterpolate(float width, float height, ArrayList<DisplayOption> points) { float weights = 0; DisplayOption p = points.get(0); if (dist(width, height, p.minWidthDps, p.minHeightDps) == 0) { return p; } DisplayOption out = new DisplayOption(); out.name = ""; 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)); if (!TextUtils.isEmpty(out.name)) { out.name += "&"; } out.name += "<" + (p.grid != null ? p.grid.name : "not found") + "," + p.name + ">"; } return out.multiply(1.0f / weights); }
//获取默认的gridname,在该版本中返回的是空值 private String getDefaultGridName(Context context) { String defaultGridName = ""; DesktopGridController gridController = mMonitor.getDesktopGridController(); if (gridController != null) { defaultGridName = gridController.getDefaultGridName(); if (mMonitor.getSRController() != null && !gridController.isGridNameValid(defaultGridName)) { if (LogUtils.DEBUG) { LogUtils.d(TAG, "The default grid name configured is invalid:" + defaultGridName); } defaultGridName = mMonitor.getSRController().getGridNameFromStorage(context); } if (LogUtils.DEBUG) { LogUtils.d(TAG, "getDefaultGridName: defaultGridName = " + defaultGridName); } } return defaultGridName;
}
GridOption和DiaplayOption
private static final class DisplayOption { private final GridOption grid; private String name; private final float minWidthDps; private final float minHeightDps; private final boolean canBeDefault; private float iconSize; private float landscapeIconSize; private float iconTextSize; ... } public static final class GridOption { public static final String TAG_NAME = "grid-option"; public final String name; public final int numRows; public final int numColumns; private final int numFolderRows; private final int numFolderColumns; private final int numHotseatIcons; private final int defaultLayoutId; private final int demoModeLayoutId; private final SparseArray<TypedValue> extraAttrs;
##com.android.launcher3.prefs.xml 这是Launcher3应用主要的sharedprefs文件,作为分析时的参考 `/data/data/com.android.launcher3/shared_prefs/com.android.launcher3.prefs.xml` ``` < <?xml version='1.0' encoding='utf-8' standalone='yes' ?> <map> <int name="launcher.home_bounce_count" value="4" /> <string name="migration_src_workspace_size">2,2</string> <boolean name="pref_add_icon_to_home" value="true" /> <int name="migration_src_hotseat_count" value="0" /> <boolean name="pref_add_icon_to_home_initialized" value="true" /> <boolean name="sl_EMPTY_DATABASE_CREATED" value="true" /> <int name="migration_src_density_dpi" value="140" /> <string name="idp_grid_name">3_by_3</string> </map>
MultiModeController.java
packages/apps/Launcher3/src/com/sprd/ext/multimode/MultiModeController.java
import static com.android.launcher3.LauncherProvider.SCHEMA_VERSION; //28 public static String getKeyByMode(Context context, String originalKey) { return getKeyByMode(context, originalKey, SCHEMA_VERSION, isSingleLayerMode(context)); } //参数:key, 数据库版本,是单层还是双层显示 public static String getKeyByMode( Context context, String originalKey, int dbVersion, boolean isSingleLayerMode) { initControllerIfNeeded(context); return MultiModeUtilities.getKeyByMode(originalKey, isSingleLayerMode, dbVersion); } public static String getKeyByPreMode(Context context, String originalKey) { return getKeyByMode(context, originalKey, SCHEMA_VERSION, !isSingleLayerMode(context)); } public static boolean isSingleLayerMode() { throwIfControllerNotInited(); return sIsSingleLayerMode; //返回变量sIsSingleLayerMode } public static void setSingleLayerMode(Context context, boolean isSingleMode) { MultiModeUtilities.syncSaveNewModel(context, isSingleMode ? MultiModeUtilities.SINGLE : MultiModeUtilities.DUAL); //sIsSingleLayerMode在构造方法中赋值 sIsSingleLayerMode = MultiModeUtilities.isSingleLayerMode(context); sIsDefaultMode = MultiModeUtilities.isDefaultMode(context); } public MultiModeController(Context context, LauncherAppMonitor monitor) { super(context); //是否支持动态显示 sIsSupportDynamicChange = MultiModeUtilities.isSupportDynamicHomeStyle(context); //是否是单层显示 sIsSingleLayerMode = MultiModeUtilities.isSingleLayerMode(context); sIsDefaultMode = MultiModeUtilities.isDefaultMode(context); monitor.registerCallback(mAppMonitorCallback); LogUtils.d(TAG, this); } //是否支持动态变化 public static boolean isSupportDynamicChange() { throwIfControllerNotInited(); return sIsSupportDynamicChange; } public static void setSupportDynamicChange(boolean isSupport) { sIsSupportDynamicChange = isSupport; }
MultiModeUtilities
packages/apps/Launcher3/src/com/sprd/ext/multimode/MultiModeUtilities.java
static final String SINGLE = "single"; static final String DUAL = "dual"; static final String SL_PREFIX = "sl_"; //判断是否是单层显示 static boolean isSingleLayerMode(Context context) { return FeatureOption.SPRD_MULTI_MODE_SUPPORT.get() && SINGLE.equals(getHomeScreenStylePrefValue(context)); } //在sharepref中获取显示风格的值 static String getHomeScreenStylePrefValue(Context context) { if (context == null) { return DUAL; } Resources res = context.getResources(); return Utilities.getPrefs(context) .getString(LauncherSettingsExtension.PREF_HOME_SCREEN_STYLE_KEY, res.getString(R.string.default_home_screen_style)); //默认值为R.string.default_home_screen_style } // We add SL_PREFIX only single layer mode & support dynamic change. static String getKeyByMode(String originalKey, boolean isSingleMode, int dbVersion) { if (TextUtils.isEmpty(originalKey)) { throw new RuntimeException("getKeyByMode() the original key is empty!"); } String outKey = originalKey; //如果支持多模式,再进行判断,如果不支持,则使用双层模式 //我修改了show_home_screen_style_settings的值为false,outKey=idp_grid_name if (MultiModeController.isSupportDynamicChange()) { switch (dbVersion) { case 27: // Android P db version is 27. outKey = isSingleMode ? SINGLE + "_" + originalKey : DUAL + "_" + originalKey; break; default: //我的设备是单层显示,所以返回的是sl_idp_grid_name outKey = isSingleMode ? SL_PREFIX + originalKey : originalKey; break; } } return outKey; } //是否支持动态显示 static boolean isSupportDynamicHomeStyle(Context context) { return FeatureOption.SPRD_MULTI_MODE_SUPPORT.get() && context.getResources().getBoolean(R.bool.show_home_screen_style_settings); }
LauncherSettingsExtension
packages/apps/Launcher3/src/com/sprd/ext/LauncherSettingsExtension.java
public static final String PREF_HOME_SCREEN_STYLE_KEY = "pref_home_screen_style";
FeatureOption
packages/apps/Launcher3/src/com/sprd/ext/FeatureOption.java
public static final TogglableFlag SPRD_MULTI_MODE_SUPPORT = new TogglableFlag( "SPRD_MULTI_MODE_SUPPORT", getProp("ro.launcher.multimode"), "enable user can select user aosp mode or singlelayer mode"); public static final TogglableFlag SPRD_DESKTOP_GRID_SUPPORT = new TogglableFlag( "SPRD_DESKTOP_GRID_SUPPORT", getProp("ro.launcher.desktopgrid"), "enable allows customization of the columns and rows on the desktop");
config_ext.xml
packages/apps/Launcher3/res/values/config_ext.xml
//从上面分析可以得出结论 <!--default value of launcher style allapps or singlelayer 是否显示单层/双层设置显示--> <bool name="show_home_screen_style_settings">false</bool> <!--The value must be dual or single 默认为单层还是双层--> <string name="default_home_screen_style" translatable="false">dual</string>
device_profiles.xml
位置:packages/apps/Launcher3/res/xml/device_profiles.xml
<profiles xmlns:launcher="http://schemas.android.com/apk/res-auto" > <grid-option launcher:name="2_by_2" launcher:numRows="2" launcher:numColumns="2" launcher:numFolderRows="2" launcher:numFolderColumns="2" launcher:numHotseatIcons="3" 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> <grid-option launcher:name="3_by_3" launcher:numRows="3" launcher:numColumns="3" launcher:numFolderRows="2" launcher:numFolderColumns="3" launcher:numHotseatIcons="3" 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> <grid-option launcher:name="4_by_4" launcher:numRows="4" launcher:numColumns="4" launcher:numFolderRows="3" launcher:numFolderColumns="4" launcher:numHotseatIcons="4" 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" /> <display-option launcher:name="Stubby" launcher:minWidthDps="255" launcher:minHeightDps="450" launcher:iconImageSize="48" launcher:iconTextSize="13.0" launcher:canBeDefault="true" /> <display-option launcher:name="Nexus S" launcher:minWidthDps="296" launcher:minHeightDps="491.33" launcher:iconImageSize="48" launcher:iconTextSize="13.0" launcher:canBeDefault="true" /> <display-option launcher:name="Nexus 4" launcher:minWidthDps="359" launcher:minHeightDps="567" launcher:iconImageSize="54" launcher:iconTextSize="13.0" launcher:canBeDefault="true" /> <display-option launcher:name="Nexus 5" launcher:minWidthDps="335" launcher:minHeightDps="567" launcher:iconImageSize="54" launcher:iconTextSize="13.0" launcher:canBeDefault="true" /> </grid-option> </profiles>