按照惯例 Launcher3 源码存在两份,分别位于 package/app/和vendor/mediatek/proprietary/packages/apps/下,vendor下的mk中使用 LOCAL_OVERRIDES_PACKAGES 属性覆盖 package 下的源码,所以我们要改的源码就是 vendor 下的。但是在 Q 中并不是这样的,编译后的Launcher3 app 路径为 product/priv-app/MtkLauncher3QuickStep/,来看下 mk,可以看到编译 MtkLauncher3QuickStep 并没有引用当前目录下的源码文件,并没有 LOCAL_SRC_FILES := \,而是引入静态库 Launcher3QuickStepLib
LOCAL_STATIC_ANDROID_LIBRARIES := Launcher3QuickStepLib
vendor\mediatek\proprietary\packages\apps\Launcher3\Android.mk
#
# Build rule for Quickstep app.
#
include $(CLEAR_VARS)
LOCAL_USE_AAPT2 := true
LOCAL_MODULE_TAGS := optional
....
LOCAL_PACKAGE_NAME := MtkLauncher3QuickStep
LOCAL_PRIVILEGED_MODULE := true
LOCAL_PRODUCT_MODULE := true
LOCAL_OVERRIDES_PACKAGES := Home Launcher2 Launcher3 Launcher3QuickStep
LOCAL_REQUIRED_MODULES := privapp_whitelist_com.android.launcher3
LOCAL_RESOURCE_DIR := \
$(LOCAL_PATH)/quickstep/res \
$(LOCAL_PATH)/quickstep/recents_ui_overrides/res
LOCAL_FULL_LIBS_MANIFEST_FILES := \
$(LOCAL_PATH)/AndroidManifest.xml \
$(LOCAL_PATH)/AndroidManifest-common.xml
LOCAL_MANIFEST_FILE := quickstep/AndroidManifest.xml
LOCAL_JACK_COVERAGE_INCLUDE_FILTER := com.android.launcher3.*
include $(BUILD_PACKAGE)
静态库编译在 packages\apps\Launcher3\Android.mk,所以不管你怎么修改 vendor下 Launcher3 的源码,编译都不生效,要去修改
packages\apps\Launcher3
#
# Build rule for Quickstep library.
#
include $(CLEAR_VARS)
.....
LOCAL_MODULE := Launcher3QuickStepLib
LOCAL_PRIVILEGED_MODULE := true
LOCAL_STATIC_ANDROID_LIBRARIES := \
Launcher3CommonDepsLib \
SecondaryDisplayLauncherLib
LOCAL_SRC_FILES := \
$(call all-java-files-under, src) \
$(call all-java-files-under, quickstep/src) \
$(call all-java-files-under, quickstep/recents_ui_overrides/src) \
$(call all-java-files-under, src_flags) \
$(call all-java-files-under, src_shortcuts_overrides)
LOCAL_RESOURCE_DIR := \
$(LOCAL_PATH)/quickstep/res \
$(LOCAL_PATH)/quickstep/recents_ui_overrides/res
LOCAL_PROGUARD_ENABLED := disabled
LOCAL_MANIFEST_FILE := quickstep/AndroidManifest.xml
include $(BUILD_STATIC_JAVA_LIBRARY)
为了方便调试修改我们编译 userdebug 版本,可直接 push 替换效果。为了避免每次改动后整编烧写的麻烦,我还是直接修改 vendor中的Launcher3,新建一个android.mk,单独编译时引入当前路径下的源码,效果确认后再拷贝至 package 中 Launcher3 即可,每次修改源码后 mmm 得到 apk,push 进去,kill 进程查看效果。
vendor\mediatek\proprietary\packages\apps\Launcher3\Android.mk
LOCAL_PATH := $(call my-dir)
#
# Build rule for Quickstep app.
#
include $(CLEAR_VARS)
LOCAL_USE_AAPT2 := true
LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_ANDROID_LIBRARIES := Launcher3QuickStepLib
LOCAL_PROGUARD_ENABLED := disabled
ifneq (,$(wildcard frameworks/base))
LOCAL_PRIVATE_PLATFORM_APIS := true
else
LOCAL_SDK_VERSION := system_current
LOCAL_MIN_SDK_VERSION := 26
endif
LOCAL_PACKAGE_NAME := MtkLauncher3QuickStep
LOCAL_PRIVILEGED_MODULE := true
LOCAL_PRODUCT_MODULE := true
LOCAL_OVERRIDES_PACKAGES := Home Launcher2 Launcher3 Launcher3QuickStep
LOCAL_REQUIRED_MODULES := privapp_whitelist_com.android.launcher3
LOCAL_SRC_FILES := \
$(call all-java-files-under, src) \
$(call all-java-files-under, quickstep/src)
LOCAL_RESOURCE_DIR := \
$(LOCAL_PATH)/quickstep/res \
$(LOCAL_PATH)/quickstep/recents_ui_overrides/res
LOCAL_FULL_LIBS_MANIFEST_FILES := \
$(LOCAL_PATH)/AndroidManifest.xml \
$(LOCAL_PATH)/AndroidManifest-common.xml
LOCAL_MANIFEST_FILE := quickstep/AndroidManifest.xml
LOCAL_JACK_COVERAGE_INCLUDE_FILTER := com.android.launcher3.*
include $(BUILD_PACKAGE)
# ==================================================
include $(call all-makefiles-under,$(LOCAL_PATH))
修改位置
packages\apps\Launcher3\src\com\android\launcher3\Workspace.java
注释 bindAndInitFirstWorkspaceScreen() 中 if (qsb == null) 开始到结尾
public void bindAndInitFirstWorkspaceScreen(View qsb) {
if (!FeatureFlags.QSB_ON_FIRST_SCREEN) {
return;
}
// Add the first page
CellLayout firstPage = insertNewWorkspaceScreen(Workspace.FIRST_SCREEN_ID, 0);
if (FeatureFlags.PULLDOWN_SEARCH) {
.....
}
//add don't show google quick search box[qsb]
// Always add a QSB on the first screen.
/*if (qsb == null) {
// In transposed layout, we add the QSB in the Grid. As workspace does not touch the
// edges, we do not need a full width QSB.
qsb = LayoutInflater.from(getContext())
.inflate(R.layout.search_container_workspace,firstPage, false);
}
CellLayout.LayoutParams lp = new CellLayout.LayoutParams(0, 0, firstPage.getCountX(), 1);
lp.canReorder = false;
if (!firstPage.addViewToCellLayout(qsb, 0, R.id.search_container_workspace, lp, true)) {
Log.e(TAG, "Failed to add to item at (0, 0) to CellLayout");
}*/
//add don't show google quick search box[qsb]
}
修改位置
packages\apps\Launcher3\src\com\android\launcher3\allapps\AllAppsContainerView.java
在 onFinishInflate() 中添加一行 mSearchContainer.setVisibility(View.GONE);
@Override
protected void onFinishInflate() {
super.onFinishInflate();
....
mSearchContainer = findViewById(R.id.search_container_all_apps);
mSearchUiManager = (SearchUiManager) mSearchContainer;
mSearchUiManager.initialize(mApps, mAppsRecyclerView);
/// add this code don't show all app quick search box
mSearchContainer.setVisibility(View.GONE);
......
}
packages\apps\Launcher3\src\com\android\launcher3\allapps\AllAppsTransitionController.java
注释setAlphas() 中的 mAppsView.getSearchUiManager()
public void setAlphas(int visibleElements, AnimationConfig config, AnimatorSetBuilder builder) {
PropertySetter setter = config == null ? NO_ANIM_PROPERTY_SETTER
: config.getPropertySetter(builder);
boolean hasHeaderExtra = (visibleElements & ALL_APPS_HEADER_EXTRA) != 0;
boolean hasContent = (visibleElements & ALL_APPS_CONTENT) != 0;
Interpolator allAppsFade = builder.getInterpolator(ANIM_ALL_APPS_FADE, LINEAR);
setter.setViewAlpha(mAppsView.getContentView(), hasContent ? 1 : 0, allAppsFade);
setter.setViewAlpha(mAppsView.getScrollBar(), hasContent ? 1 : 0, allAppsFade);
mAppsView.getFloatingHeaderView().setContentVisibility(hasHeaderExtra, hasContent, setter,
allAppsFade);
///annotaion this code don't show all app quick search box
//mAppsView.getSearchUiManager().setContentVisibility(visibleElements, setter, allAppsFade);
setter.setInt(mScrimView, ScrimView.DRAG_HANDLE_ALPHA,
(visibleElements & VERTICAL_SWIPE_INDICATOR) != 0 ? 255 : 0, allAppsFade);
}
之前版本 lp.gravity 都在 DeviceProfile 中修改,Q 中移到了 Hotseat 类里面
@Override
public void setInsets(Rect insets) {
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
DeviceProfile grid = mActivity.getWallpaperDeviceProfile();
insets = grid.getInsets();
if (grid.isVerticalBarLayout()) {
lp.height = ViewGroup.LayoutParams.MATCH_PARENT;
if (grid.isSeascape()) {
lp.gravity = Gravity.LEFT;
lp.width = grid.hotseatBarSizePx + insets.left;
} else {
lp.gravity = Gravity.RIGHT;
lp.width = grid.hotseatBarSizePx + insets.right;
}
} else {
lp.gravity = Gravity.BOTTOM;
lp.width = ViewGroup.LayoutParams.MATCH_PARENT;
lp.height = grid.hotseatBarSizePx + insets.bottom;
}
Rect padding = grid.getHotseatLayoutPadding();
setPadding(padding.left, padding.top, padding.right, padding.bottom);
setLayoutParams(lp);
InsettableFrameLayout.dispatchInsets(this, insets);
}
为了不影响其它间距计算我们去修改 grid.isVerticalBarLayout()
packages\apps\Launcher3\src\com\android\launcher3\DeviceProfile.java
将 transposeLayoutWithOrientation 置为 false 即可
// Some more constants
transposeLayoutWithOrientation = false;
//res.getBoolean(R.bool.hotseat_transpose_layout_with_orientation);
public boolean isVerticalBarLayout() {
return isLandscape && transposeLayoutWithOrientation;
}
经过 log 打印发现 display == DISPLAY_WORKSPACE 时,textsize 和 padding 均为 0,所以文字不显示,直接注释当前 if,和
display == DISPLAY_ALL_APPS 共用逻辑
packages/apps/Launcher3/src/com/android/launcher3/BubbleTextView.java
public BubbleTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mActivity = ActivityContext.lookupContext(context);
mSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.BubbleTextView, defStyle, 0);
mLayoutHorizontal = a.getBoolean(R.styleable.BubbleTextView_layoutHorizontal, false);
int display = a.getInteger(R.styleable.BubbleTextView_iconDisplay, DISPLAY_WORKSPACE);
final int defaultIconSize;
//annotaion code because textsize and padding is 0 don't show text
/* if (display == DISPLAY_WORKSPACE) {
android.util.Log.i("Launcher3","WorkspaceItemInfo");
DeviceProfile grid = mActivity.getWallpaperDeviceProfile();
setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.iconTextSizePx);//0
setCompoundDrawablePadding(grid.iconDrawablePaddingPx);//0
defaultIconSize = grid.iconSizePx;
android.util.Log.i("Launcher3","DISPLAY_WORKSPACE iconTextSizePx="+grid.iconTextSizePx);
android.util.Log.i("Launcher3","DISPLAY_WORKSPACE iconDrawablePaddingPx="+grid.iconDrawablePaddingPx);
} else */if (display == DISPLAY_WORKSPACE || display == DISPLAY_ALL_APPS) {
DeviceProfile grid = mActivity.getDeviceProfile();
setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.allAppsIconTextSizePx);
setCompoundDrawablePadding(grid.allAppsIconDrawablePaddingPx);
defaultIconSize = grid.allAppsIconSizePx;
android.util.Log.d("Launcher3","DISPLAY_ALL_APPS allAppsIconTextSizePx="+grid.allAppsIconTextSizePx);
android.util.Log.d("Launcher3","DISPLAY_ALL_APPS allAppsIconDrawablePaddingPx="+grid.allAppsIconDrawablePaddingPx);
}
packages/apps/Launcher3/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java
private Drawable normalizeAndWrapToAdaptiveIcon(Drawable icon, boolean shrinkNonAdaptiveIcons,
RectF outIconBounds, float[] outScale) {
float scale = 1f;
android.util.Log.e("Launcher3","normalizeAndWrapToAdaptiveIcon...");
//annotation for don't add white mask outshape when targetsdk >= 26
/*if (shrinkNonAdaptiveIcons && ATLEAST_OREO) {
if (mWrapperIcon == null) {
mWrapperIcon = mContext.getDrawable(R.drawable.adaptive_icon_drawable_wrapper)
.mutate();
}
AdaptiveIconDrawable dr = (AdaptiveIconDrawable) mWrapperIcon;
dr.setBounds(0, 0, 1, 1);
boolean[] outShape = new boolean[1];
scale = getNormalizer().getScale(icon, outIconBounds, dr.getIconMask(), outShape);
if (!(icon instanceof AdaptiveIconDrawable) && !outShape[0]) {
FixedScaleDrawable fsd = ((FixedScaleDrawable) dr.getForeground());
fsd.setDrawable(icon);
fsd.setScale(scale);
icon = dr;
scale = getNormalizer().getScale(icon, outIconBounds, null, null);
((ColorDrawable) dr.getBackground()).setColor(mWrapperBackgroundColor);
}
} else {
scale = getNormalizer().getScale(icon, outIconBounds, null, null);
}*/
scale = getNormalizer().getScale(icon, outIconBounds, null, null);
outScale[0] = scale;
return icon;
}