Bug 1403653 - Part 3 - Use the Lightweight Theme accent colour for the status bar in normal mode. r?nechen
If the theme doesn't provide an accent colour, we try determining something appropriate ourselves.
MozReview-Commit-ID: B5TSeIFsBIK
--- a/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
+++ b/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
@@ -108,16 +108,17 @@ import org.mozilla.gecko.home.HomePager.
import org.mozilla.gecko.home.HomePanelsManager;
import org.mozilla.gecko.home.HomeScreen;
import org.mozilla.gecko.home.SearchEngine;
import org.mozilla.gecko.icons.Icons;
import org.mozilla.gecko.icons.IconsHelper;
import org.mozilla.gecko.icons.decoders.FaviconDecoder;
import org.mozilla.gecko.icons.decoders.IconDirectoryEntry;
import org.mozilla.gecko.icons.decoders.LoadFaviconResult;
+import org.mozilla.gecko.lwt.LightweightTheme;
import org.mozilla.gecko.media.VideoPlayer;
import org.mozilla.gecko.menu.GeckoMenu;
import org.mozilla.gecko.menu.GeckoMenuItem;
import org.mozilla.gecko.mma.MmaDelegate;
import org.mozilla.gecko.mozglue.GeckoLoader;
import org.mozilla.gecko.mozglue.SafeIntent;
import org.mozilla.gecko.notifications.NotificationHelper;
import org.mozilla.gecko.overlays.ui.ShareDialog;
@@ -179,30 +180,30 @@ import java.lang.reflect.Method;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
-import java.util.Set;
import java.util.regex.Pattern;
import static org.mozilla.gecko.mma.MmaDelegate.NEW_TAB;
public class BrowserApp extends GeckoApp
implements ActionModePresenter,
AnchoredPopup.OnVisibilityChangeListener,
BookmarkEditFragment.Callbacks,
BrowserSearch.OnEditSuggestionListener,
BrowserSearch.OnSearchListener,
DynamicToolbarAnimator.MetricsListener,
DynamicToolbarAnimator.ToolbarChromeProxy,
LayoutInflater.Factory,
+ LightweightTheme.OnChangeListener,
OnUrlOpenListener,
OnUrlOpenInBackgroundListener,
PropertyAnimator.PropertyAnimationListener,
TabsPanel.TabsLayoutChangeListener,
View.OnKeyListener {
private static final String LOGTAG = "GeckoBrowserApp";
private static final int TABS_ANIMATION_DURATION = 450;
@@ -636,17 +637,18 @@ public class BrowserApp extends GeckoApp
// Kick off download of app content as early as possible so that in the best case it's
// available before the user starts using the browser.
DownloadContentService.startStudy(this);
}
// This has to be prepared prior to calling GeckoApp.onCreate, because
// widget code and BrowserToolbar need it, and they're created by the
// layout, which GeckoApp takes care of.
- ((GeckoApplication) getApplication()).prepareLightweightTheme();
+ final GeckoApplication app = (GeckoApplication) getApplication();
+ app.prepareLightweightTheme();
super.onCreate(savedInstanceState);
initSwitchboard(this, intent, isInAutomation);
initTelemetryUploader(isInAutomation);
mBrowserChrome = (ViewGroup) findViewById(R.id.browser_chrome);
mActionBarFlipper = (ViewFlipper) findViewById(R.id.browser_actionbar);
@@ -671,16 +673,18 @@ public class BrowserApp extends GeckoApp
}
@Override
public boolean onTouch(View v, MotionEvent event) {
return false;
}
});
+ app.getLightweightTheme().addListener(this);
+
mProgressView = (AnimatedProgressBar) findViewById(R.id.page_progress);
mDynamicToolbar.setLayerView(mLayerView);
mProgressView.setDynamicToolbar(mDynamicToolbar);
mBrowserToolbar.setProgressBar(mProgressView);
// Initialize Tab History Controller.
tabHistoryController = new TabHistoryController(new OnShowTabHistory() {
@Override
@@ -1546,16 +1550,19 @@ public class BrowserApp extends GeckoApp
}
if (mProgressView != null) {
mProgressView.setDynamicToolbar(null);
}
mDynamicToolbar.destroy();
+ final GeckoApplication app = (GeckoApplication) getApplication();
+ app.getLightweightTheme().removeListener(this);
+
if (mBrowserToolbar != null)
mBrowserToolbar.onDestroy();
if (mFindInPageBar != null) {
mFindInPageBar.onDestroy();
mFindInPageBar = null;
}
@@ -2325,18 +2332,17 @@ public class BrowserApp extends GeckoApp
if (mDoorHangerPopup != null) {
mDoorHangerPopup.enable();
}
for (final BrowserAppDelegate delegate : delegates) {
delegate.onTabsTrayHidden(this, mTabsPanel);
}
- final boolean isPrivate = mBrowserToolbar.isPrivateMode();
- WindowUtil.setStatusBarColor(this, isPrivate);
+ refreshStatusBarColor();
}
@Override
public boolean autoHideTabs() {
if (areTabsShown()) {
hideTabs();
return true;
}
@@ -4443,9 +4449,24 @@ public class BrowserApp extends GeckoApp
new EditBookmarkDialog(this).show(pageUrl);
}
}
@Override
public void onEditBookmark(@NonNull Bundle bundle) {
new EditBookmarkTask(this, bundle).execute();
}
+
+ @Override
+ public void onLightweightThemeChanged() {
+ refreshStatusBarColor();
+ }
+
+ @Override
+ public void onLightweightThemeReset() {
+ refreshStatusBarColor();
+ }
+
+ private void refreshStatusBarColor() {
+ final boolean isPrivate = mBrowserToolbar.isPrivateMode();
+ WindowUtil.setStatusBarColor(BrowserApp.this, isPrivate);
+ }
}
--- a/mobile/android/base/java/org/mozilla/gecko/lwt/LightweightTheme.java
+++ b/mobile/android/base/java/org/mozilla/gecko/lwt/LightweightTheme.java
@@ -28,16 +28,17 @@ import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
+import android.support.annotation.ColorInt;
import android.text.TextUtils;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewParent;
public class LightweightTheme implements BundleEventListener {
private static final String LOGTAG = "GeckoLightweightTheme";
@@ -45,17 +46,17 @@ public class LightweightTheme implements
private static final String PREFS_URL = "lightweightTheme.headerURL";
private static final String PREFS_COLOR = "lightweightTheme.color";
private static final String ASSETS_PREFIX = "resource://android/assets/";
private final Application mApplication;
private Bitmap mBitmap;
- private int mColor;
+ private @ColorInt int mColor;
private boolean mIsLight;
public static interface OnChangeListener {
// The View should change its background/text color.
public void onLightweightThemeChanged();
// The View should reset to its default background/text color.
public void onLightweightThemeReset();
@@ -230,18 +231,18 @@ public class LightweightTheme implements
// The lightweight theme image's width and height.
final int bitmapWidth = bitmap.getWidth();
final int bitmapHeight = bitmap.getHeight();
try {
mColor = Color.parseColor(color);
} catch (Exception e) {
// Malformed or missing color.
- // Default to TRANSPARENT.
- mColor = Color.TRANSPARENT;
+ // We attempt calculating an accent colour ourselves, falling back to TRANSPARENT.
+ mColor = BitmapUtils.getDominantColor(bitmap, Color.TRANSPARENT);
}
// Calculate the luminance to determine if it's a light or a dark theme.
double luminance = (0.2125 * ((mColor & 0x00FF0000) >> 16)) +
(0.7154 * ((mColor & 0x0000FF00) >> 8)) +
(0.0721 * (mColor & 0x000000FF));
mIsLight = luminance > 110;
@@ -312,16 +313,23 @@ public class LightweightTheme implements
*
* @return True if the theme is light.
*/
public boolean isLightTheme() {
return mIsLight;
}
/**
+ * @return The accent color of the theme.
+ */
+ public @ColorInt int getColor() {
+ return mColor;
+ }
+
+ /**
* Crop the image based on the position of the view on the window.
* Either the View or one of its ancestors might have scrolled or translated.
* This value should be taken into account while mapping the View to the Bitmap.
*
* @param view The view requesting a cropped bitmap.
*/
private Bitmap getCroppedBitmap(View view) {
if (mBitmap == null || view == null) {
--- a/mobile/android/base/java/org/mozilla/gecko/util/WindowUtil.java
+++ b/mobile/android/base/java/org/mozilla/gecko/util/WindowUtil.java
@@ -1,50 +1,63 @@
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko.util;
import android.app.Activity;
+import android.graphics.Color;
import android.os.Build;
import android.support.annotation.ColorInt;
import android.support.annotation.ColorRes;
import android.support.v4.content.ContextCompat;
import android.view.View;
import android.view.Window;
+import org.mozilla.gecko.GeckoApplication;
import org.mozilla.gecko.R;
+import org.mozilla.gecko.lwt.LightweightTheme;
public class WindowUtil {
public static void setTabsTrayStatusBarColor(final Activity activity) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return;
}
setStatusBarColorRes(activity, R.color.status_bar_bg_color_tabs_tray, true);
}
public static void setStatusBarColor(final Activity activity, final boolean isPrivate) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return;
}
- final @ColorRes int colorResId;
+ final @ColorInt int color;
final boolean isDarkTheme;
if (HardwareUtils.isTablet()) {
- colorResId = R.color.status_bar_bg_color_tablet;
+ color = ContextCompat.getColor(activity, R.color.status_bar_bg_color_tablet);
isDarkTheme = true;
} else {
- colorResId = isPrivate ? R.color.status_bar_bg_color_private : R.color.status_bar_bg_color;
- isDarkTheme = isPrivate;
+ LightweightTheme theme = ((GeckoApplication) activity.getApplication()).getLightweightTheme();
+ @ColorInt int themeColor = theme.getColor();
+ if (isPrivate) {
+ color = ContextCompat.getColor(activity, R.color.status_bar_bg_color_private);
+ isDarkTheme = true;
+ } else if (theme.isEnabled() && themeColor != Color.TRANSPARENT) {
+ color = themeColor;
+ isDarkTheme = !theme.isLightTheme();
+ } else {
+ color = ContextCompat.getColor(activity, R.color.status_bar_bg_color);
+ isDarkTheme = false;
+ }
}
- setStatusBarColorRes(activity, colorResId, isDarkTheme);
+ setStatusBarColor(activity, color, isDarkTheme);
}
public static void setStatusBarColorRes(final Activity activity, final @ColorRes int colorResId,
final boolean isDarkTheme) {
final int backgroundColor = ContextCompat.getColor(activity, colorResId);
setStatusBarColor(activity, backgroundColor, isDarkTheme);
}