fix: Link app drawer background opacity to correct colors (#6636)

Signed-off-by: Pun Butrach <pun.butrach@gmail.com>
This commit is contained in:
Pun Butrach authored and GitHub committed 2026-05-10 20:05:50 +08:00
1 parent b8066dc7e4
commit 0bd70f3bd0
5 files changed
+112 -43

No files matched your search

@@ -42,18 +42,22 @@ import android.util.Log
import android.util.Size
import android.view.View
import android.widget.TextView
import androidx.compose.ui.util.lerp
import androidx.core.graphics.ColorUtils
import androidx.core.graphics.createBitmap
import androidx.core.graphics.luminance
import androidx.core.os.UserManagerCompat
import app.lawnchair.preferences.PreferenceManager
import app.lawnchair.preferences2.PreferenceManager2
import app.lawnchair.theme.color.ColorOption
import app.lawnchair.theme.color.tokens.ColorTokens
import com.android.launcher3.BaseActivity
import com.android.launcher3.BuildConfig
import com.android.launcher3.R
import com.android.launcher3.Utilities
import com.android.launcher3.util.Executors.MAIN_EXECUTOR
import com.android.launcher3.util.Themes
import com.android.launcher3.views.ActivityContext
import com.android.systemui.shared.system.QuickStepContract
import com.patrykmichalik.opto.core.firstBlocking
import java.io.ByteArrayOutputStream
@@ -145,8 +149,9 @@ fun supportsRoundedCornersOnWindows(context: Context): Boolean {
fun overrideAllAppsTextColor(textView: TextView) {
val context = textView.context
val luminance = getAllAppsBaseColor(context, ColorTokens.AllAppsScrimColor.resolveColor(context)).luminance
val opacity = PreferenceManager.getInstance(context).drawerOpacity.get()
if (opacity <= 0.3f) {
if (luminance > 0.5f || opacity <= 0.3f) {
textView.setTextColor(Themes.getAttrColor(context, R.attr.allAppsAlternateTextColor))
}
}
@@ -180,17 +185,20 @@ fun getFolderBackgroundAlpha(context: Context): Int {
return (prefs2.folderBackgroundOpacity.firstBlocking() * 255).toInt()
}
fun getAllAppsScrimColor(context: Context): Int {
val opacity = PreferenceManager.getInstance(context).drawerOpacity.get()
/** Apply Lawnchair custom allapps colour to the provided colour */
private fun getAllAppsBaseColor(context: Context, defaultColor: Int): Int {
val prefs2 = PreferenceManager2.getInstance(context)
var scrimColor = ColorTokens.AllAppsScrimColor.resolveColor(context)
val colorOptions: ColorOption = prefs2.appDrawerBackgroundColor.firstBlocking()
val color = colorOptions.colorPreferenceEntry.lightColor.invoke(context)
if (color != 0) {
scrimColor = color
}
val alpha = (opacity * 255).roundToInt()
return ColorUtils.setAlphaComponent(scrimColor, alpha)
val baseColor = if (color != 0) color else defaultColor
return ColorUtils.setAlphaComponent(baseColor, 255)
}
/** Apply Lawnchair custom allapps opacity and colour to the provided colour */
fun getAllAppsBackgroundColor(context: Context, defaultColor: Int): Int {
val prefs = PreferenceManager.getInstance(context)
val userOpacity = prefs.drawerOpacity.get()
return ColorUtils.setAlphaComponent(getAllAppsBaseColor(context, defaultColor), (userOpacity * 255).roundToInt())
}
fun Context.checkPackagePermission(packageName: String, permissionName: String): Boolean {
@@ -280,13 +280,13 @@ public class TaskbarAllAppsSlideInView extends AbstractSlideInView<TaskbarOverla
protected int getScrimColor(Context context) {
if (!mActivityContext.getDeviceProfile().shouldShowAllAppsOnSheet()) {
// Always use an opaque scrim if there's no sheet.
// Lawnchair-TODO-Colour: Check R.color.materialColorSurfaceDim
return context.getResources().getColor(R.color.materialColorSurfaceDim);
return ColorTokens.AllAppsScrimColor.resolveColor(context);
} else if (!Flags.allAppsBlur()) {
// If there's a sheet but no blur, use the old scrim color.
return ColorTokens.WidgetsPickerScrim.resolveColor(context);
return LawnchairUtilsKt.getAllAppsBackgroundColor(context,
ColorTokens.WidgetsPickerScrim.resolveColor(context));
}
return LawnchairUtilsKt.getAllAppsScrimColor(context);
return ColorTokens.AllAppsScrimColor.resolveColor(context);
}
@Override
@@ -29,7 +29,6 @@ import com.android.launcher3.Flags;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
import com.android.launcher3.util.Themes;
import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.views.ScrimColors;
import com.android.quickstep.util.BaseDepthController;
@@ -37,7 +36,6 @@ import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
import java.util.concurrent.TimeUnit;
import app.lawnchair.LawnchairLauncher;
import app.lawnchair.util.LawnchairUtilsKt;
/**
@@ -213,12 +211,13 @@ public class AllAppsState extends LauncherState {
int backgroundColor;
if (!launcher.getDeviceProfile().shouldShowAllAppsOnSheet()) {
// Always use an opaque scrim if there's no sheet.
backgroundColor = ColorTokens.SurfaceDimColor.resolveColor(launcher);
backgroundColor = ColorTokens.AllAppsScrimColor.resolveColor(launcher);
} else if (!Flags.allAppsBlur()) {
// If there's a sheet but no blur, use the old scrim color.
backgroundColor = ColorTokens.WidgetsPickerScrim.resolveColor(launcher);
backgroundColor = LawnchairUtilsKt.getAllAppsBackgroundColor(launcher,
ColorTokens.WidgetsPickerScrim.resolveColor(launcher));
} else {
backgroundColor = LawnchairUtilsKt.getAllAppsScrimColor(launcher);
backgroundColor = ColorTokens.AllAppsScrimColor.resolveColor(launcher);
}
return new ScrimColors(backgroundColor, /* foregroundColor */ Color.TRANSPARENT);
}
@@ -26,6 +26,7 @@ import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCH
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_TAP_ON_PERSONAL_TAB;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_TAP_ON_WORK_TAB;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.launcher3.util.ScrollableLayoutManager.PREDICTIVE_BACK_MIN_SCALE;
import static com.android.launcher3.views.RecyclerViewFastScroller.FastScrollerLocation.ALL_APPS_SCROLLER;
import static com.android.window.flags2.Flags.predictiveBackThreeButtonNav;
@@ -50,6 +51,7 @@ import android.os.UserManager;
import android.util.AttributeSet;
import android.util.Log;
import android.util.SparseArray;
import android.view.CrossWindowBlurListeners;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
@@ -57,6 +59,7 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.ViewOutlineProvider;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.RelativeLayout;
@@ -66,6 +69,7 @@ import androidx.annotation.Px;
import androidx.annotation.VisibleForTesting;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.graphics.ColorUtils;
import androidx.core.math.MathUtils;
import androidx.core.util.Consumer;
import androidx.recyclerview.widget.RecyclerView;
@@ -114,6 +118,7 @@ import app.lawnchair.font.FontManager;
import app.lawnchair.preferences.PreferenceManager;
import app.lawnchair.preferences2.PreferenceManager2;
import app.lawnchair.theme.color.tokens.ColorTokens;
import app.lawnchair.util.LawnchairUtilsKt;
import app.lawnchair.ui.StretchRecyclerViewContainer;
/**
@@ -199,9 +204,14 @@ public class ActivityAllAppsContainerView<T extends Context & ActivityContext>
private int mTabsProtectionAlpha;
@Nullable private AllAppsTransitionController mAllAppsTransitionController;
@Nullable private java.util.function.Consumer<Boolean> mCrossWindowBlurListener;
private final PreferenceManager2 pref2;
private final PreferenceManager pref;
// LC-Note: Allapps cache colour
private int mCachedBottomSheetBgColor;
public ActivityAllAppsContainerView(Context context) {
this(context, null);
}
@@ -346,6 +356,9 @@ public class ActivityAllAppsContainerView<T extends Context & ActivityContext>
mBottomSheetBackgroundColorLegacy = ColorTokens.SurfaceDimColor.resolveColor(getContext());
// LC-Note: Update our allapps cached colour
updateBottomSheetBackgroundColor();
updateBackgroundVisibility(mActivityContext.getDeviceProfile());
mSearchUiManager.initializeSearch(this);
}
@@ -354,19 +367,44 @@ public class ActivityAllAppsContainerView<T extends Context & ActivityContext>
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (isSearchBarFloating()) {
// Note: for Taskbar this is removed in TaskbarAllAppsController#cleanUpOverlay when the
// panel is closed. Can't do so in onDetach because we are also a child of drag layer
// so can't remove its views during that dispatch.
mActivityContext.getDragLayer().addView(mSearchContainer);
mSearchUiDelegate.onInitializeSearchBar();
}
mActivityContext.addOnDeviceProfileChangeListener(this);
if (Utilities.ATLEAST_S) {
java.util.function.Consumer<Boolean> listener = enabled -> {
if (updateBottomSheetBackgroundColor(enabled)) {
invalidate();
}
};
mCrossWindowBlurListener = listener;
UI_HELPER_EXECUTOR.execute(() -> {
try {
CrossWindowBlurListeners.getInstance()
.addListener(MAIN_EXECUTOR, listener);
} catch (Throwable t) {
// LC-Ignored
}
});
}
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mActivityContext.removeOnDeviceProfileChangeListener(this);
if (mCrossWindowBlurListener != null) {
java.util.function.Consumer<Boolean> listener = mCrossWindowBlurListener;
UI_HELPER_EXECUTOR.execute(() -> {
try {
CrossWindowBlurListeners.getInstance()
.removeListener(listener);
} catch (Throwable t) {
// LC-Ignored
}
});
mCrossWindowBlurListener = null;
}
}
public SearchUiManager getSearchUiManager() {
@@ -864,22 +902,17 @@ public class ActivityAllAppsContainerView<T extends Context & ActivityContext>
}
protected int getHeaderColor(float blendRatio) {
float opacity = 0.0f;
var showHeaderBackground = PreferenceExtensionsKt.firstBlocking(
pref2.getAppDrawerSearchBarBackground());
if (showHeaderBackground) {
opacity = pref.getDrawerOpacity().get();
}
var colorOptions = PreferenceExtensionsKt.firstBlocking(pref2.getAppDrawerBackgroundColor());
var color = colorOptions.getColorPreferenceEntry().getLightColor().invoke(mActivityContext);
if (color != 0) {
mScrimColor = color;
}
if (!mActivityContext.getDeviceProfile().shouldShowAllAppsOnSheet()) {
float opacity = mSearchContainer.getAlpha();
var showHeaderBackground = PreferenceExtensionsKt.firstBlocking(
pref2.getAppDrawerSearchBarBackground());
if (showHeaderBackground) {
opacity = pref.getDrawerOpacity().get();
}
opacity = MathUtils.clamp(opacity, 0f, 1f);
return ColorUtils.setAlphaComponent(
ColorUtils.blendARGB(mScrimColor, mHeaderProtectionColor, blendRatio),
(int) (opacity * 255));
ColorUtils.blendARGB(getBackgroundColor(), mHeaderProtectionColor, blendRatio),
Math.round(opacity * 255));
}
return isBackgroundBlurEnabled()
? ColorUtils.setAlphaComponent(mHeaderProtectionColor, (int) (blendRatio * 255))
@@ -891,15 +924,32 @@ public class ActivityAllAppsContainerView<T extends Context & ActivityContext>
? getBottomSheetBackgroundColor() : mScrimColor;
}
// LC-Note: Hey! We cache this! see updateBottomSheetBackgroundColor() for more details.
int getBottomSheetBackgroundColor() {
return mCachedBottomSheetBgColor;
}
// LC-Note: This is getBottomSheetBackgroundColor() in AOSP, but we refactor it to cache our prefs.
private boolean updateBottomSheetBackgroundColor() {
return updateBottomSheetBackgroundColor(mActivityContext.isAllAppsBackgroundBlurEnabled());
}
// LC-Note: For listener to avoid querying stale value.
private boolean updateBottomSheetBackgroundColor(boolean blurEnabled) {
int defaultColor;
if (!Flags.allAppsBlur()) {
return mBottomSheetBackgroundColorLegacy;
defaultColor = mBottomSheetBackgroundColorLegacy;
} else if (!blurEnabled) {
defaultColor = mBottomSheetBackgroundColorBlurFallback;
} else {
defaultColor = mBottomSheetBackgroundColorOverBlur;
}
if (!mActivityContext.isAllAppsBackgroundBlurEnabled()) {
// Don't apply any alpha if the blur is disabled.
return mBottomSheetBackgroundColorBlurFallback;
int newColor = LawnchairUtilsKt.getAllAppsBackgroundColor(mActivityContext, defaultColor);
if (mCachedBottomSheetBgColor != newColor) {
mCachedBottomSheetBgColor = newColor;
return true;
}
return mBottomSheetBackgroundColorOverBlur;
return false;
}
boolean isBackgroundBlurEnabled() {
@@ -1095,9 +1145,18 @@ public class ActivityAllAppsContainerView<T extends Context & ActivityContext>
}
updateBackgroundVisibility(dp);
boolean needsInvalidate = false;
int navBarScrimColor = Themes.getNavBarScrimColor(mActivityContext);
if (mNavBarScrimPaint.getColor() != navBarScrimColor) {
mNavBarScrimPaint.setColor(navBarScrimColor);
needsInvalidate = true;
}
// LC-Note: Update our allapps cached colour
if (updateBottomSheetBackgroundColor()) {
needsInvalidate = true;
}
if (needsInvalidate) {
invalidate();
}
}
@@ -19,10 +19,12 @@ import static com.android.app.animation.Interpolators.DECELERATE;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_ALLAPPS;
import android.graphics.Color;
import app.lawnchair.theme.color.tokens.ColorTokens;
import app.lawnchair.util.LawnchairUtilsKt;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
import com.android.launcher3.util.Themes;
import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.views.ScrimColors;
@@ -101,8 +103,9 @@ public class AllAppsState extends LauncherState {
public ScrimColors getWorkspaceScrimColor(Launcher launcher) {
return new ScrimColors(
/* backgroundColor */ launcher.getDeviceProfile().getDeviceProperties().isTablet()
? launcher.getResources().getColor(R.color.widgets_picker_scrim)
: Themes.getAttrColor(launcher, R.attr.allAppsScrimColor),
? LawnchairUtilsKt.getAllAppsBackgroundColor(launcher,
ColorTokens.WidgetsPickerScrim.resolveColor(launcher))
: ColorTokens.AllAppsScrimColor.resolveColor(launcher),
/* foregroundColor */ Color.TRANSPARENT);
}
}