From 8392c823a938d527ac826904c0e8dbe7310d6176 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Tue, 20 Jun 2017 10:03:56 -0700 Subject: [PATCH] Fixing various system UI flags not getting updated properly on theme changes. SystemUiController manages various system UI flags in priorty order and merges all the states before applying the syste flags. Fixing WallpaperColors when it was not handing wallpaper change properly in some cases Change-Id: I915442818e7888c97c81f63c8ea9f3c13053eb2c --- src/com/android/launcher3/BaseActivity.java | 9 +++ src/com/android/launcher3/Launcher.java | 36 +-------- .../allapps/AllAppsTransitionController.java | 23 +++--- .../dynamicui/WallpaperColorInfo.java | 2 +- .../launcher3/util/SystemUiController.java | 79 +++++++++++++++++++ .../launcher3/widget/WidgetsBottomSheet.java | 17 ++-- 6 files changed, 113 insertions(+), 53 deletions(-) create mode 100644 src/com/android/launcher3/util/SystemUiController.java diff --git a/src/com/android/launcher3/BaseActivity.java b/src/com/android/launcher3/BaseActivity.java index 08cd955a54..2b59ede476 100644 --- a/src/com/android/launcher3/BaseActivity.java +++ b/src/com/android/launcher3/BaseActivity.java @@ -22,11 +22,13 @@ import android.content.ContextWrapper; import android.view.View.AccessibilityDelegate; import com.android.launcher3.logging.UserEventDispatcher; +import com.android.launcher3.util.SystemUiController; public abstract class BaseActivity extends Activity { protected DeviceProfile mDeviceProfile; protected UserEventDispatcher mUserEventDispatcher; + protected SystemUiController mSystemUiController; public DeviceProfile getDeviceProfile() { return mDeviceProfile; @@ -54,4 +56,11 @@ public abstract class BaseActivity extends Activity { } return ((BaseActivity) ((ContextWrapper) context).getBaseContext()); } + + public SystemUiController getSystemUiController() { + if (mSystemUiController == null) { + mSystemUiController = new SystemUiController(getWindow()); + } + return mSystemUiController; + } } diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index bb32a4563b..66aab43283 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -126,6 +126,7 @@ import com.android.launcher3.util.MultiHashMap; import com.android.launcher3.util.PackageManagerHelper; import com.android.launcher3.util.PackageUserKey; import com.android.launcher3.util.PendingRequestArgs; +import com.android.launcher3.util.SystemUiController; import com.android.launcher3.util.TestingUtils; import com.android.launcher3.util.Themes; import com.android.launcher3.util.Thunk; @@ -470,9 +471,8 @@ public class Launcher extends BaseActivity // Listen for broadcasts screen off registerReceiver(mReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF)); - if (Themes.getAttrBoolean(this, R.attr.isWorkspaceDarkText)) { - activateLightSystemBars(true, true, true); - } + getSystemUiController().updateUiState(SystemUiController.UI_STATE_BASE_WINDOW, + Themes.getAttrBoolean(this, R.attr.isWorkspaceDarkText)); } @Override @@ -519,36 +519,6 @@ public class Launcher extends BaseActivity } } - /** - * Sets the status and/or nav bar to be light or not. Light status bar means dark icons. - * @param isLight make sure the system bar is light. - * @param statusBar if true, make the status bar theme match the isLight param. - * @param navBar if true, make the nav bar theme match the isLight param. - */ - public void activateLightSystemBars(boolean isLight, boolean statusBar, boolean navBar) { - int oldSystemUiFlags = getWindow().getDecorView().getSystemUiVisibility(); - int newSystemUiFlags = oldSystemUiFlags; - if (isLight) { - if (statusBar) { - newSystemUiFlags |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; - } - if (navBar && Utilities.isAtLeastO()) { - newSystemUiFlags |= View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR; - } - } else { - if (statusBar) { - newSystemUiFlags &= ~(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); - } - if (navBar && Utilities.isAtLeastO()) { - newSystemUiFlags &= ~(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - } - - if (newSystemUiFlags != oldSystemUiFlags) { - getWindow().getDecorView().setSystemUiVisibility(newSystemUiFlags); - } - } - private LauncherCallbacks mLauncherCallbacks; public void onPostCreate(Bundle savedInstanceState) { diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java index 2d8310bbe4..faadce4c92 100644 --- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java +++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java @@ -28,6 +28,7 @@ import com.android.launcher3.graphics.GradientView; import com.android.launcher3.graphics.ScrimView; import com.android.launcher3.userevent.nano.LauncherLogProto.Action; import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; +import com.android.launcher3.util.SystemUiController; import com.android.launcher3.util.Themes; import com.android.launcher3.util.TouchController; @@ -71,7 +72,6 @@ public class AllAppsTransitionController implements TouchController, VerticalPul private final VerticalPullDetector mDetector; private final ArgbEvaluator mEvaluator; private final boolean mIsDarkTheme; - private final boolean mIsWorkspaceDarkText; // Animation in this class is controlled by a single variable {@link mProgress}. // Visually, it represents top y coordinate of the all apps container if multiplied with @@ -114,7 +114,6 @@ public class AllAppsTransitionController implements TouchController, VerticalPul mEvaluator = new ArgbEvaluator(); mAllAppsBackgroundColor = Themes.getAttrColor(l, android.R.attr.colorPrimary); mIsDarkTheme = Themes.getAttrBoolean(mLauncher, R.attr.isMainColorDark); - mIsWorkspaceDarkText = Themes.getAttrBoolean(mLauncher, R.attr.isWorkspaceDarkText); } @Override @@ -278,15 +277,21 @@ public class AllAppsTransitionController implements TouchController, VerticalPul } private void updateLightStatusBar(float shift) { - // Do not modify status bar in dark theme or on landscape as all apps is not full bleed. - if (mIsDarkTheme || mIsWorkspaceDarkText || (!FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS - && mLauncher.getDeviceProfile().isVerticalBarLayout())) { + // Do not modify status bar on landscape as all apps is not full bleed. + if (!FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS + && mLauncher.getDeviceProfile().isVerticalBarLayout()) { return; } - // Use a light status bar (dark icons) if all apps is behind at least half of the status - // bar. If the status bar is already light due to wallpaper extraction, keep it that way. - boolean forceLight = shift <= mStatusBarHeight / 2; - mLauncher.activateLightSystemBars(forceLight, true /* statusBar */, true /* navBar */); + + // Use a light system UI (dark icons) if all apps is behind at least half of the status bar. + boolean forceChange = shift <= mStatusBarHeight / 2; + if (forceChange) { + mLauncher.getSystemUiController().updateUiState( + SystemUiController.UI_STATE_ALL_APPS, !mIsDarkTheme); + } else { + mLauncher.getSystemUiController().updateUiState( + SystemUiController.UI_STATE_ALL_APPS, 0); + } } private void updateAllAppsBg(float progress) { diff --git a/src/com/android/launcher3/dynamicui/WallpaperColorInfo.java b/src/com/android/launcher3/dynamicui/WallpaperColorInfo.java index 856a26ca86..512e89a419 100644 --- a/src/com/android/launcher3/dynamicui/WallpaperColorInfo.java +++ b/src/com/android/launcher3/dynamicui/WallpaperColorInfo.java @@ -61,7 +61,7 @@ public class WallpaperColorInfo implements WallpaperManagerCompat.OnColorsChange @Override public void onColorsChanged(WallpaperColorsCompat colors, int which) { - if (which == FLAG_SYSTEM) { + if ((which & FLAG_SYSTEM) != 0) { boolean wasDarkTheme = mIsDark; boolean didSupportDarkText = mSupportsDarkText; update(colors); diff --git a/src/com/android/launcher3/util/SystemUiController.java b/src/com/android/launcher3/util/SystemUiController.java new file mode 100644 index 0000000000..6b5b095c78 --- /dev/null +++ b/src/com/android/launcher3/util/SystemUiController.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3.util; + +import android.view.View; +import android.view.Window; + +import com.android.launcher3.Utilities; + +/** + * Utility class to manage various window flags to control system UI. + */ +public class SystemUiController { + + // Various UI states in increasing order of priority + public static final int UI_STATE_BASE_WINDOW = 0; + public static final int UI_STATE_ALL_APPS = 1; + public static final int UI_STATE_WIDGET_BOTTOM_SHEET = 2; + + public static final int FLAG_LIGHT_NAV = 1 << 0; + public static final int FLAG_DARK_NAV = 1 << 1; + public static final int FLAG_LIGHT_STATUS = 1 << 2; + public static final int FLAG_DARK_STATUS = 1 << 3; + + private final Window mWindow; + private final int[] mStates = new int[3]; + + public SystemUiController(Window window) { + mWindow = window; + } + + public void updateUiState(int uiState, boolean isLight) { + updateUiState(uiState, isLight + ? (FLAG_LIGHT_NAV | FLAG_LIGHT_STATUS) : (FLAG_DARK_NAV | FLAG_DARK_STATUS)); + } + + public void updateUiState(int uiState, int flags) { + if (mStates[uiState] == flags) { + return; + } + mStates[uiState] = flags; + + int oldFlags = mWindow.getDecorView().getSystemUiVisibility(); + // Apply the state flags in priority order + int newFlags = oldFlags; + for (int stateFlag : mStates) { + if (Utilities.isAtLeastO()) { + if ((stateFlag & FLAG_LIGHT_NAV) != 0) { + newFlags |= View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR; + } else if ((stateFlag & FLAG_DARK_NAV) != 0) { + newFlags &= ~(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + } + + if ((stateFlag & FLAG_LIGHT_STATUS) != 0) { + newFlags |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; + } else if ((stateFlag & FLAG_DARK_STATUS) != 0) { + newFlags &= ~(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); + } + } + if (newFlags != oldFlags) { + mWindow.getDecorView().setSystemUiVisibility(newFlags); + } + } +} diff --git a/src/com/android/launcher3/widget/WidgetsBottomSheet.java b/src/com/android/launcher3/widget/WidgetsBottomSheet.java index 5fe00c2d59..cea58b9945 100644 --- a/src/com/android/launcher3/widget/WidgetsBottomSheet.java +++ b/src/com/android/launcher3/widget/WidgetsBottomSheet.java @@ -48,6 +48,7 @@ import com.android.launcher3.dragndrop.DragOptions; import com.android.launcher3.model.WidgetItem; import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.launcher3.util.PackageUserKey; +import com.android.launcher3.util.SystemUiController; import com.android.launcher3.util.TouchController; import java.util.List; @@ -69,7 +70,6 @@ public class WidgetsBottomSheet extends AbstractFloatingView implements Insettab private Interpolator mFastOutSlowInInterpolator; private VerticalPullDetector.ScrollInterpolator mScrollInterpolator; private Rect mInsets; - private boolean mWasNavBarLight; private VerticalPullDetector mVerticalPullDetector; public WidgetsBottomSheet(Context context, AttributeSet attrs) { @@ -103,8 +103,6 @@ public class WidgetsBottomSheet extends AbstractFloatingView implements Insettab onWidgetsBound(); - mWasNavBarLight = (mLauncher.getWindow().getDecorView().getSystemUiVisibility() - & View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR) != 0; mLauncher.getDragLayer().addView(this); measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED); setTranslationY(mTranslationYClosed); @@ -180,7 +178,8 @@ public class WidgetsBottomSheet extends AbstractFloatingView implements Insettab return; } mIsOpen = true; - setLightNavBar(true); + mLauncher.getSystemUiController().updateUiState( + SystemUiController.UI_STATE_WIDGET_BOTTOM_SHEET, SystemUiController.FLAG_LIGHT_NAV); if (animate) { mOpenCloseAnimator.setValues(new PropertyListBuilder() .translationY(mTranslationYOpen).build()); @@ -211,7 +210,8 @@ public class WidgetsBottomSheet extends AbstractFloatingView implements Insettab mIsOpen = false; mVerticalPullDetector.finishedScrolling(); ((ViewGroup) getParent()).removeView(WidgetsBottomSheet.this); - setLightNavBar(mWasNavBarLight); + mLauncher.getSystemUiController().updateUiState( + SystemUiController.UI_STATE_WIDGET_BOTTOM_SHEET, 0); } }); mOpenCloseAnimator.setInterpolator(mVerticalPullDetector.isIdleState() @@ -219,15 +219,12 @@ public class WidgetsBottomSheet extends AbstractFloatingView implements Insettab mOpenCloseAnimator.start(); } else { setTranslationY(mTranslationYClosed); - setLightNavBar(mWasNavBarLight); + mLauncher.getSystemUiController().updateUiState( + SystemUiController.UI_STATE_WIDGET_BOTTOM_SHEET, 0); mIsOpen = false; } } - private void setLightNavBar(boolean lightNavBar) { - mLauncher.activateLightSystemBars(lightNavBar, false /* statusBar */, true /* navBar */); - } - @Override protected boolean isOfType(@FloatingViewType int type) { return (type & TYPE_WIDGETS_BOTTOM_SHEET) != 0;