Merge "Show icon in PendingAppWidgetHostView immediately." into ub-launcher3-dorval-polish
diff --git a/res/drawable-xxhdpi/all_apps_alpha_mask.png b/res/drawable-xxhdpi/all_apps_alpha_mask.png
new file mode 100644
index 0000000..ed53ff9
--- /dev/null
+++ b/res/drawable-xxhdpi/all_apps_alpha_mask.png
Binary files differ
diff --git a/res/layout-land/launcher.xml b/res/layout-land/launcher.xml
index 6c1b1d3..565728c 100644
--- a/res/layout-land/launcher.xml
+++ b/res/layout-land/launcher.xml
@@ -32,6 +32,8 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
+ <include layout="@layout/gradient_scrim" />
+
<!-- The workspace contains 5 screens of cells -->
<!-- DO NOT CHANGE THE ID -->
<com.android.launcher3.Workspace
diff --git a/res/layout-port/launcher.xml b/res/layout-port/launcher.xml
index 1fdf546..eccb824 100644
--- a/res/layout-port/launcher.xml
+++ b/res/layout-port/launcher.xml
@@ -33,6 +33,8 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
+ <include layout="@layout/gradient_scrim" />
+
<!-- The workspace contains 5 screens of cells -->
<!-- DO NOT CHANGE THE ID -->
<com.android.launcher3.Workspace
diff --git a/res/layout-sw720dp/launcher.xml b/res/layout-sw720dp/launcher.xml
index 9ef3394..7fad517 100644
--- a/res/layout-sw720dp/launcher.xml
+++ b/res/layout-sw720dp/launcher.xml
@@ -32,6 +32,8 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
+ <include layout="@layout/gradient_scrim" />
+
<!-- The workspace contains 5 screens of cells -->
<!-- DO NOT CHANGE THE ID -->
<com.android.launcher3.Workspace
diff --git a/res/layout/gradient_scrim.xml b/res/layout/gradient_scrim.xml
new file mode 100644
index 0000000..02c39eb
--- /dev/null
+++ b/res/layout/gradient_scrim.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
+ <com.android.launcher3.graphics.RadialGradientView
+ android:id="@+id/gradient_bg"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:visibility="gone"
+ app:layout_ignoreInsets="true"/>
+
+ <com.android.launcher3.graphics.ScrimView
+ android:id="@+id/scrim_bg"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:visibility="gone"
+ app:layout_ignoreInsets="true"/>
+</merge>
\ No newline at end of file
diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java
index 128d956..ab82c98 100644
--- a/src/com/android/launcher3/Hotseat.java
+++ b/src/com/android/launcher3/Hotseat.java
@@ -72,7 +72,9 @@
mBackgroundColor = ColorUtils.setAlphaComponent(
Themes.getAttrColor(context, android.R.attr.colorPrimary), 0);
mBackground = new ColorDrawable(mBackgroundColor);
- setBackground(mBackground);
+ if (!FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS) {
+ setBackground(mBackground);
+ }
}
public CellLayout getLayout() {
@@ -179,6 +181,10 @@
}
public void updateColor(ExtractedColors extractedColors, boolean animate) {
+ if (FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS) {
+ // not hotseat visible
+ return;
+ }
if (!mHasVerticalHotseat) {
int color = extractedColors.getColor(ExtractedColors.HOTSEAT_INDEX);
if (mBackgroundColorAnimator != null) {
diff --git a/src/com/android/launcher3/InfoDropTarget.java b/src/com/android/launcher3/InfoDropTarget.java
index 7b3bded..f088d11 100644
--- a/src/com/android/launcher3/InfoDropTarget.java
+++ b/src/com/android/launcher3/InfoDropTarget.java
@@ -19,6 +19,8 @@
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
+import android.graphics.Rect;
+import android.os.Bundle;
import android.provider.Settings;
import android.util.AttributeSet;
import android.util.Log;
@@ -58,12 +60,16 @@
*/
public static boolean startDetailsActivityForInfo(
ItemInfo info, Launcher launcher, DropTargetResultCallback callback) {
+ return startDetailsActivityForInfo(info, launcher, callback, null, null);
+ }
+
+ public static boolean startDetailsActivityForInfo(ItemInfo info, Launcher launcher,
+ DropTargetResultCallback callback, Rect sourceBounds, Bundle opts) {
if (info instanceof PromiseAppInfo) {
PromiseAppInfo promiseAppInfo = (PromiseAppInfo) info;
launcher.startActivity(promiseAppInfo.getMarketIntent());
return true;
}
-
boolean result = false;
ComponentName componentName = null;
if (info instanceof AppInfo) {
@@ -78,7 +84,7 @@
if (componentName != null) {
try {
LauncherAppsCompat.getInstance(launcher)
- .showAppDetailsForProfile(componentName, info.user);
+ .showAppDetailsForProfile(componentName, info.user, sourceBounds, opts);
result = true;
} catch (SecurityException | ActivityNotFoundException e) {
Toast.makeText(launcher, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 3a50bd1..0d1e9e1 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -466,7 +466,9 @@
@Override
public void onExtractedColorsChanged() {
loadExtractedColorsAndColorItems();
-
+ if (mAllAppsController != null) {
+ mAllAppsController.onExtractedColorsChanged();
+ }
if (mLauncherCallbacks != null) {
mLauncherCallbacks.onExtractedColorsChanged();
}
@@ -2682,7 +2684,7 @@
}
@TargetApi(Build.VERSION_CODES.M)
- private Bundle getActivityLaunchOptions(View v) {
+ public Bundle getActivityLaunchOptions(View v) {
if (Utilities.ATLEAST_MARSHMALLOW) {
int left = 0, top = 0;
int width = v.getMeasuredWidth(), height = v.getMeasuredHeight();
@@ -2708,7 +2710,7 @@
return null;
}
- private Rect getViewBounds(View v) {
+ public Rect getViewBounds(View v) {
int[] pos = new int[2];
v.getLocationOnScreen(pos);
return new Rect(pos[0], pos[1], pos[0] + v.getWidth(), pos[1] + v.getHeight());
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index ca789d4..09fb953 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -125,6 +125,7 @@
// always available in the main process.
FileLog.setDir(getContext().getApplicationContext().getFilesDir());
IconShapeOverride.apply(getContext());
+ SessionCommitReceiver.applyDefaultUserPrefs(getContext());
return true;
}
diff --git a/src/com/android/launcher3/SessionCommitReceiver.java b/src/com/android/launcher3/SessionCommitReceiver.java
index 69695ae..61bcc17 100644
--- a/src/com/android/launcher3/SessionCommitReceiver.java
+++ b/src/com/android/launcher3/SessionCommitReceiver.java
@@ -16,6 +16,7 @@
package com.android.launcher3;
+import android.annotation.TargetApi;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -23,8 +24,15 @@
import android.content.pm.LauncherActivityInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageInstaller.SessionInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Build;
import android.os.Process;
import android.os.UserHandle;
+import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
@@ -35,26 +43,32 @@
/**
* BroadcastReceiver to handle session commit intent.
*/
+@TargetApi(Build.VERSION_CODES.O)
public class SessionCommitReceiver extends BroadcastReceiver {
- private static final long SESSION_IGNORE_DURATION = 3 * 60 * 60 * 1000; // 3 hours
+ private static final String TAG = "SessionCommitReceiver";
+
+ // The content provider for the add to home screen setting. It should be of the format:
+ // <package name>.addtohomescreen
+ private static final String MARKER_PROVIDER_PREFIX = ".addtohomescreen";
// Preference key for automatically adding icon to homescreen.
public static final String ADD_ICON_PREFERENCE_KEY = "pref_add_icon_to_home";
-
- private static final String KEY_FIRST_TIME = "first_session_broadcast_time";
+ public static final String ADD_ICON_PREFERENCE_INITIALIZED_KEY =
+ "pref_add_icon_to_home_initialized";
@Override
public void onReceive(Context context, Intent intent) {
- if (!isEnabled(context)) {
+ if (!isEnabled(context) || !Utilities.isAtLeastO()) {
// User has decided to not add icons on homescreen.
return;
}
SessionInfo info = intent.getParcelableExtra(PackageInstaller.EXTRA_SESSION);
UserHandle user = intent.getParcelableExtra(Intent.EXTRA_USER);
- // TODO: Verify install reason
- if (TextUtils.isEmpty(info.getAppPackageName())) {
+
+ if (TextUtils.isEmpty(info.getAppPackageName()) ||
+ info.getInstallReason() != PackageManager.INSTALL_REASON_USER) {
return;
}
@@ -63,17 +77,6 @@
return;
}
- // STOPSHIP: Remove this workaround when we start getting proper install reason
- SharedPreferences prefs = context
- .getSharedPreferences(LauncherFiles.DEVICE_PREFERENCES_KEY, 0);
- long now = System.currentTimeMillis();
- long firstTime = prefs.getLong(KEY_FIRST_TIME, now);
- prefs.edit().putLong(KEY_FIRST_TIME, firstTime).apply();
- if ((now - firstTime) < SESSION_IGNORE_DURATION) {
- Log.d("SessionCommitReceiver", "Temporarily ignoring session broadcast");
- return;
- }
-
List<LauncherActivityInfo> activities = LauncherAppsCompat.getInstance(context)
.getActivityList(info.getAppPackageName(), user);
if (activities == null || activities.isEmpty()) {
@@ -86,4 +89,68 @@
public static boolean isEnabled(Context context) {
return Utilities.getPrefs(context).getBoolean(ADD_ICON_PREFERENCE_KEY, true);
}
+
+ public static void applyDefaultUserPrefs(final Context context) {
+ if (!Utilities.isAtLeastO()) {
+ return;
+ }
+ SharedPreferences prefs = Utilities.getPrefs(context);
+ if (prefs.getAll().isEmpty()) {
+ // This logic assumes that the code is the first thing that is executed (before any
+ // shared preference is written).
+ // TODO: Move this logic to DB upgrade once we have proper support for db downgrade
+ // If it is a fresh start, just apply the default value. We use prefs.isEmpty() to infer
+ // a fresh start as put preferences always contain some values corresponding to current
+ // grid.
+ prefs.edit().putBoolean(ADD_ICON_PREFERENCE_KEY, true).apply();
+ } else if (!prefs.contains(ADD_ICON_PREFERENCE_INITIALIZED_KEY)) {
+ new PrefInitTask(context).executeOnExecutor(Utilities.THREAD_POOL_EXECUTOR);
+ }
+ }
+
+ private static class PrefInitTask extends AsyncTask<Void, Void, Void> {
+ private final Context mContext;
+
+ PrefInitTask(Context context) {
+ mContext = context;
+ }
+
+ @Override
+ protected Void doInBackground(Void... voids) {
+ boolean addIconToHomeScreenEnabled = readValueFromMarketApp();
+ Utilities.getPrefs(mContext).edit()
+ .putBoolean(ADD_ICON_PREFERENCE_KEY, addIconToHomeScreenEnabled)
+ .putBoolean(ADD_ICON_PREFERENCE_INITIALIZED_KEY, true)
+ .apply();
+ return null;
+ }
+
+ public boolean readValueFromMarketApp() {
+ // Get the marget package
+ ResolveInfo ri = mContext.getPackageManager().resolveActivity(
+ new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_APP_MARKET),
+ PackageManager.MATCH_DEFAULT_ONLY | PackageManager.MATCH_SYSTEM_ONLY);
+ if (ri == null) {
+ return true;
+ }
+
+ Cursor c = null;
+ try {
+ c = mContext.getContentResolver().query(
+ Uri.parse("content://" + ri.activityInfo.packageName
+ + MARKER_PROVIDER_PREFIX),
+ null, null, null, null);
+ if (c.moveToNext()) {
+ return c.getInt(c.getColumnIndexOrThrow(Settings.NameValueTable.VALUE)) != 0;
+ }
+ } catch (Exception e) {
+ Log.d(TAG, "Error reading add to homescreen preference", e);
+ } finally {
+ if (c != null) {
+ c.close();
+ }
+ }
+ return true;
+ }
+ }
}
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index 776ec2f..54e7dd2 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -28,6 +28,7 @@
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
+import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
@@ -645,4 +646,28 @@
hashSet.add(elem);
return hashSet;
}
+
+ /**
+ * @return creates a new alpha mask bitmap out of an existing bitmap
+ */
+ public static Bitmap convertToAlphaMask(Bitmap b, float applyAlpha) {
+ Bitmap a = Bitmap.createBitmap(b.getWidth(), b.getHeight(), Bitmap.Config.ALPHA_8);
+ Canvas c = new Canvas(a);
+ Paint paint = new Paint();
+ paint.setAlpha((int) (255f * applyAlpha));
+ c.drawBitmap(b, 0f, 0f, paint);
+ return a;
+ }
+
+ /**
+ * @return a new white 1x1 bitmap with ALPHA_8
+ */
+ public static Bitmap createOnePixBitmap() {
+ Bitmap a = Bitmap.createBitmap(1, 1, Bitmap.Config.ALPHA_8);
+ Canvas c = new Canvas(a);
+ Paint paint = new Paint();
+ paint.setColor(Color.WHITE);
+ c.drawPaint(paint);
+ return a;
+ }
}
diff --git a/src/com/android/launcher3/WidgetPreviewLoader.java b/src/com/android/launcher3/WidgetPreviewLoader.java
index c525cd4..f66995f 100644
--- a/src/com/android/launcher3/WidgetPreviewLoader.java
+++ b/src/com/android/launcher3/WidgetPreviewLoader.java
@@ -27,7 +27,6 @@
import android.os.Handler;
import android.os.UserHandle;
import android.support.annotation.Nullable;
-import android.support.v4.graphics.ColorUtils;
import android.util.Log;
import android.util.LongSparseArray;
@@ -388,10 +387,10 @@
drawable.setBounds(x, 0, x + previewWidth, previewHeight);
drawable.draw(c);
} else {
- final Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
- RectF boxRect = drawBoxWithShadow(c, p, previewWidth, previewHeight);
+ RectF boxRect = drawBoxWithShadow(c, previewWidth, previewHeight);
// Draw horizontal and vertical lines to represent individual columns.
+ final Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
p.setStyle(Paint.Style.STROKE);
p.setStrokeWidth(mContext.getResources()
.getDimension(R.dimen.widget_preview_cell_divider_width));
@@ -431,7 +430,7 @@
return preview;
}
- private RectF drawBoxWithShadow(Canvas c, Paint p, int width, int height) {
+ private RectF drawBoxWithShadow(Canvas c, int width, int height) {
Resources res = mContext.getResources();
float shadowBlur = res.getDimension(R.dimen.widget_preview_shadow_blur);
float keyShadowDistance = res.getDimension(R.dimen.widget_preview_key_shadow_distance);
@@ -439,19 +438,7 @@
RectF bounds = new RectF(shadowBlur, shadowBlur,
width - shadowBlur, height - shadowBlur - keyShadowDistance);
- p.setColor(Color.WHITE);
-
- // Key shadow
- p.setShadowLayer(shadowBlur, 0, keyShadowDistance,
- ShadowGenerator.KEY_SHADOW_ALPHA << 24);
- c.drawRoundRect(bounds, corner, corner, p);
-
- // Ambient shadow
- p.setShadowLayer(shadowBlur, 0, 0,
- ColorUtils.setAlphaComponent(Color.BLACK, ShadowGenerator.AMBIENT_SHADOW_ALPHA));
- c.drawRoundRect(bounds, corner, corner, p);
-
- p.clearShadowLayer();
+ ShadowGenerator.drawShadow(c, bounds, Color.WHITE, shadowBlur, keyShadowDistance, corner);
return bounds;
}
@@ -478,8 +465,7 @@
c.setBitmap(preview);
c.drawColor(0, PorterDuff.Mode.CLEAR);
}
- Paint p = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
- RectF boxRect = drawBoxWithShadow(c, p, size, size);
+ RectF boxRect = drawBoxWithShadow(c, size, size);
Bitmap icon = LauncherIcons.createScaledBitmapWithoutShadow(
mutateOnMainThread(info.getFullResIcon(mIconCache)), mContext, Build.VERSION_CODES.O);
@@ -487,7 +473,8 @@
boxRect.set(0, 0, iconSize, iconSize);
boxRect.offset(padding, padding);
- c.drawBitmap(icon, src, boxRect, p);
+ c.drawBitmap(icon, src, boxRect,
+ new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG));
c.setBitmap(null);
return preview;
}
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index af67631..7be8e8f 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -492,7 +492,8 @@
ViewGroup.LayoutParams navBarBgLp = navBarBg.getLayoutParams();
navBarBgLp.height = insets.bottom;
navBarBg.setLayoutParams(navBarBgLp);
- navBarBg.setVisibility(View.VISIBLE);
+ navBarBg.setVisibility(FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS
+ ? View.INVISIBLE : View.VISIBLE);
}
}
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index 30ed180..121ce4c 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -22,6 +22,10 @@
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.Workspace;
+import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.dynamicui.ExtractedColors;
+import com.android.launcher3.graphics.RadialGradientView;
+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.Themes;
@@ -91,6 +95,8 @@
// Used in discovery bounce animation to provide the transition without workspace changing.
private boolean mIsTranslateWithoutWorkspace = false;
private AnimatorSet mDiscoBounceAnimation;
+ private RadialGradientView mGradientView;
+ private ScrimView mScrimView;
public AllAppsTransitionController(Launcher l) {
mLauncher = l;
@@ -247,7 +253,9 @@
if (!mLauncher.isAllAppsVisible()) {
mLauncher.tryAndUpdatePredictedApps();
mAppsView.setVisibility(View.VISIBLE);
- mAppsView.setRevealDrawableColor(mHotseatBackgroundColor);
+ if (!FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS) {
+ mAppsView.setRevealDrawableColor(mHotseatBackgroundColor);
+ }
}
}
}
@@ -263,6 +271,36 @@
mLauncher.activateLightSystemBars(forceLight, true /* statusBar */, true /* navBar */);
}
+ private void updateAllAppsBg(float progress) {
+ // gradient
+ if (mGradientView == null) {
+ mGradientView = (RadialGradientView) mLauncher.findViewById(R.id.gradient_bg);
+ mGradientView.setVisibility(View.VISIBLE);
+ onExtractedColorsChanged();
+ }
+ mGradientView.setProgress(progress);
+
+ // scrim
+ if (mScrimView == null) {
+ mScrimView = (ScrimView) mLauncher.findViewById(R.id.scrim_bg);
+ mScrimView.setVisibility(View.VISIBLE);
+ }
+ mScrimView.setProgress(progress);
+ }
+
+ public void onExtractedColorsChanged() {
+ if (FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS) {
+ if (mGradientView != null) {
+ int color1 = mLauncher.getExtractedColors()
+ .getColor(ExtractedColors.ALLAPPS_GRADIENT_MAIN_INDEX);
+ int color2 = mLauncher.getExtractedColors()
+ .getColor(ExtractedColors.ALLAPPS_GRADIENT_SECONDARY_INDEX);
+ mGradientView.onExtractedColorsChanged(color1, color2);
+ mGradientView.requestLayout();
+ }
+ }
+ }
+
/**
* @param progress value between 0 and 1, 0 shows all apps and 1 shows workspace
*/
@@ -280,7 +318,12 @@
int bgAlpha = Color.alpha((int) mEvaluator.evaluate(alpha,
mHotseatBackgroundColor, mAllAppsBackgroundColor));
- mAppsView.setRevealDrawableColor(ColorUtils.setAlphaComponent(color, bgAlpha));
+ if (FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS) {
+ updateAllAppsBg(alpha);
+ } else {
+ mAppsView.setRevealDrawableColor(ColorUtils.setAlphaComponent(color, bgAlpha));
+ }
+
mAppsView.getContentView().setAlpha(alpha);
mAppsView.setTranslationY(shiftCurrent);
diff --git a/src/com/android/launcher3/compat/LauncherAppsCompat.java b/src/com/android/launcher3/compat/LauncherAppsCompat.java
index 01d0e17..472cfc9 100644
--- a/src/com/android/launcher3/compat/LauncherAppsCompat.java
+++ b/src/com/android/launcher3/compat/LauncherAppsCompat.java
@@ -78,7 +78,8 @@
Rect sourceBounds, Bundle opts);
public abstract ApplicationInfo getApplicationInfo(
String packageName, int flags, UserHandle user);
- public abstract void showAppDetailsForProfile(ComponentName component, UserHandle user);
+ public abstract void showAppDetailsForProfile(ComponentName component, UserHandle user,
+ Rect sourceBounds, Bundle opts);
public abstract void addOnAppsChangedCallback(OnAppsChangedCallbackCompat listener);
public abstract void removeOnAppsChangedCallback(OnAppsChangedCallbackCompat listener);
public abstract boolean isPackageEnabledForProfile(String packageName, UserHandle user);
@@ -142,4 +143,8 @@
return null;
}
}
+
+ public void showAppDetailsForProfile(ComponentName component, UserHandle user) {
+ showAppDetailsForProfile(component, user, null, null);
+ }
}
diff --git a/src/com/android/launcher3/compat/LauncherAppsCompatVL.java b/src/com/android/launcher3/compat/LauncherAppsCompatVL.java
index 58683db..647c315 100644
--- a/src/com/android/launcher3/compat/LauncherAppsCompatVL.java
+++ b/src/com/android/launcher3/compat/LauncherAppsCompatVL.java
@@ -95,8 +95,9 @@
}
@Override
- public void showAppDetailsForProfile(ComponentName component, UserHandle user) {
- mLauncherApps.startAppDetailsActivity(component, user, null, null);
+ public void showAppDetailsForProfile(ComponentName component, UserHandle user,
+ Rect sourceBounds, Bundle opts) {
+ mLauncherApps.startAppDetailsActivity(component, user, sourceBounds, opts);
}
@Override
diff --git a/src/com/android/launcher3/dynamicui/ColorExtractionService.java b/src/com/android/launcher3/dynamicui/ColorExtractionService.java
index 9379a72..f6b02aa 100644
--- a/src/com/android/launcher3/dynamicui/ColorExtractionService.java
+++ b/src/com/android/launcher3/dynamicui/ColorExtractionService.java
@@ -63,8 +63,11 @@
// We can't extract colors from live wallpapers, so just use the default color always.
extractedColors.updateHotseatPalette(null);
- if (FeatureFlags.QSB_IN_HOTSEAT) {
+ if (FeatureFlags.QSB_IN_HOTSEAT || FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS) {
extractedColors.updateWallpaperThemePalette(null);
+ if (FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS) {
+ extractedColors.updateAllAppsGradientPalette(null);
+ }
}
} else {
// We extract colors for the hotseat and status bar separately,
@@ -75,8 +78,12 @@
extractedColors.updateStatusBarPalette(getStatusBarPalette());
}
- if (FeatureFlags.QSB_IN_HOTSEAT) {
- extractedColors.updateWallpaperThemePalette(getWallpaperPalette());
+ if (FeatureFlags.QSB_IN_HOTSEAT || FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS) {
+ Palette wallpaperPalette = getWallpaperPalette();
+ extractedColors.updateWallpaperThemePalette(wallpaperPalette);
+ if (FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS) {
+ extractedColors.updateAllAppsGradientPalette(wallpaperPalette);
+ }
}
}
diff --git a/src/com/android/launcher3/dynamicui/ExtractedColors.java b/src/com/android/launcher3/dynamicui/ExtractedColors.java
index 2e52a0b..3c4aba1 100644
--- a/src/com/android/launcher3/dynamicui/ExtractedColors.java
+++ b/src/com/android/launcher3/dynamicui/ExtractedColors.java
@@ -18,6 +18,7 @@
import android.content.Context;
import android.graphics.Color;
+import android.support.annotation.Nullable;
import android.support.v4.graphics.ColorUtils;
import android.support.v7.graphics.Palette;
import android.util.Log;
@@ -42,12 +43,24 @@
public static final int HOTSEAT_INDEX = 1;
public static final int STATUS_BAR_INDEX = 2;
public static final int WALLPAPER_VIBRANT_INDEX = 3;
+ public static final int ALLAPPS_GRADIENT_MAIN_INDEX = 4;
+ public static final int ALLAPPS_GRADIENT_SECONDARY_INDEX = 5;
private static final int VERSION;
private static final int[] DEFAULT_VALUES;
static {
- if (FeatureFlags.QSB_IN_HOTSEAT) {
+ if (FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS) {
+ VERSION = 3;
+ DEFAULT_VALUES = new int[] {
+ VERSION, // VERSION_INDEX
+ 0x40FFFFFF, // HOTSEAT_INDEX: White with 25% alpha
+ DEFAULT_DARK, // STATUS_BAR_INDEX
+ 0xFFCCCCCC, // WALLPAPER_VIBRANT_INDEX
+ 0xFF000000, // ALLAPPS_GRADIENT_MAIN_INDEX
+ 0xFF000000 // ALLAPPS_GRADIENT_SECONDARY_INDEX
+ };
+ } else if (FeatureFlags.QSB_IN_HOTSEAT) {
VERSION = 2;
DEFAULT_VALUES = new int[] {
VERSION, // VERSION_INDEX
@@ -142,9 +155,20 @@
DEFAULT_LIGHT : DEFAULT_DARK);
}
- public void updateWallpaperThemePalette(Palette wallpaperPalette) {
+ public void updateWallpaperThemePalette(@Nullable Palette wallpaperPalette) {
int defaultColor = DEFAULT_VALUES[WALLPAPER_VIBRANT_INDEX];
setColorAtIndex(WALLPAPER_VIBRANT_INDEX, wallpaperPalette == null
? defaultColor : wallpaperPalette.getVibrantColor(defaultColor));
}
+
+ public void updateAllAppsGradientPalette(@Nullable Palette wallpaperPalette) {
+ // TODO b/37089857 will be modified to take the system extracted colors into account
+ int idx;
+ idx = ALLAPPS_GRADIENT_MAIN_INDEX;
+ setColorAtIndex(idx, wallpaperPalette == null
+ ? DEFAULT_VALUES[idx] : wallpaperPalette.getDarkVibrantColor(DEFAULT_VALUES[idx]));
+ idx = ALLAPPS_GRADIENT_SECONDARY_INDEX;
+ setColorAtIndex(idx, wallpaperPalette == null
+ ? DEFAULT_VALUES[idx] : wallpaperPalette.getVibrantColor(DEFAULT_VALUES[idx]));
+ }
}
diff --git a/src/com/android/launcher3/graphics/LauncherIcons.java b/src/com/android/launcher3/graphics/LauncherIcons.java
index 746a639..53521f2 100644
--- a/src/com/android/launcher3/graphics/LauncherIcons.java
+++ b/src/com/android/launcher3/graphics/LauncherIcons.java
@@ -265,7 +265,7 @@
final int top = (textureHeight-height) / 2;
sOldBounds.set(icon.getBounds());
- if (icon instanceof AdaptiveIconDrawable) {
+ if (Utilities.isAtLeastO() && icon instanceof AdaptiveIconDrawable) {
int offset = Math.min(left, top);
int size = Math.max(width, height);
icon.setBounds(offset, offset, offset + size, offset + size);
diff --git a/src/com/android/launcher3/graphics/RadialGradientView.java b/src/com/android/launcher3/graphics/RadialGradientView.java
new file mode 100644
index 0000000..cf6851c
--- /dev/null
+++ b/src/com/android/launcher3/graphics/RadialGradientView.java
@@ -0,0 +1,146 @@
+/*
+ * 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.graphics;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.RadialGradient;
+import android.graphics.RectF;
+import android.graphics.Shader;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.animation.DecelerateInterpolator;
+
+import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+
+/**
+ * Draws a translucent radial gradient background from an initial state with progress 0.0 to a
+ * final state with progress 1.0;
+ */
+public class RadialGradientView extends View {
+
+ public static final int DEFAULT_COLOR_1 = Color.WHITE;
+ public static final int DEFAULT_COLOR_2 = Color.BLACK;
+
+ private static Bitmap sFinalGradientMask;
+ private static Bitmap sAlphaGradientMask;
+
+ // TODO needs to be cleaned up once design finalizes
+ static class Config {
+ // dimens
+ final float gradientCenterX = 0.5f;
+ final float gradientCenterY = 1.05f;
+ final float gradientHeadStartFactor = 0.35f;
+ final float gradientAlphaMaskLengthDp = 700;
+ // interpolation
+ final boolean useGradientAlphaDecel = false;
+ final float decelFactorForGradientAlpha = 2f;
+ // colors
+ final float finalGradientAlpha = 0.75f;
+ int color1 = DEFAULT_COLOR_1;
+ int color2 = DEFAULT_COLOR_2;
+ }
+
+ private final RectF mAlphaMaskRect = new RectF();
+ private final RectF mFinalMaskRect = new RectF();
+ private final Paint mPaint = new Paint();
+ private final Config mConfig = new Config();
+ private final DecelerateInterpolator mDecelInterpolator;
+ private float mProgress;
+ private int mWidth;
+ private int mHeight;
+ private final int mMaskHeight;
+ private final Context mAppContext;
+
+ public RadialGradientView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ this.mAppContext = context.getApplicationContext();
+ this.mDecelInterpolator = new DecelerateInterpolator(mConfig.decelFactorForGradientAlpha);
+ this.mMaskHeight = Utilities.pxFromDp(mConfig.gradientAlphaMaskLengthDp,
+ mAppContext.getResources().getDisplayMetrics());
+
+ if (sFinalGradientMask == null) {
+ sFinalGradientMask = Utilities.convertToAlphaMask(
+ Utilities.createOnePixBitmap(), mConfig.finalGradientAlpha);
+ }
+ if (sAlphaGradientMask == null) {
+ Bitmap alphaMaskFromResource = BitmapFactory.decodeResource(context.getResources(),
+ R.drawable.all_apps_alpha_mask);
+ sAlphaGradientMask = Utilities.convertToAlphaMask(
+ alphaMaskFromResource, mConfig.finalGradientAlpha);
+ }
+ }
+
+ public void onExtractedColorsChanged(int color1, int color2) {
+ mConfig.color1 = color1;
+ mConfig.color2 = color2;
+ if (mWidth + mHeight > 0) {
+ createRadialShader();
+ }
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ this.mWidth = getMeasuredWidth();
+ this.mHeight = getMeasuredHeight();
+ if (mWidth + mHeight > 0) {
+ createRadialShader();
+ }
+ }
+
+ // only being called when colors change
+ private void createRadialShader() {
+ float radius = Math.max(mHeight, mWidth) * mConfig.gradientCenterY;
+
+ float posScreenBottom = (radius - mHeight) / radius; // center lives below screen
+ RadialGradient shader = new RadialGradient(
+ mWidth * mConfig.gradientCenterX,
+ mHeight * mConfig.gradientCenterY,
+ radius,
+ new int[] {mConfig.color1, mConfig.color1, mConfig.color2},
+ new float[] {0f, posScreenBottom, 1f},
+ Shader.TileMode.CLAMP);
+ mPaint.setShader(shader);
+ }
+
+ public void setProgress(float progress) {
+ this.mProgress = progress;
+ invalidate();
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ float head = mConfig.gradientHeadStartFactor;
+ float linearProgress = head + (mProgress * (1f - head));
+ float adjustProgress = mConfig.useGradientAlphaDecel
+ ? mDecelInterpolator.getInterpolation(linearProgress)
+ : linearProgress;
+ float startMaskY = (1f - adjustProgress) * mHeight - mMaskHeight * adjustProgress;
+
+ mAlphaMaskRect.set(0, startMaskY, mWidth, startMaskY + mMaskHeight);
+ mFinalMaskRect.set(0, startMaskY + mMaskHeight, mWidth, mHeight);
+ canvas.drawBitmap(sAlphaGradientMask, null, mAlphaMaskRect, mPaint);
+ canvas.drawBitmap(sFinalGradientMask, null, mFinalMaskRect, mPaint);
+ }
+
+}
\ No newline at end of file
diff --git a/src/com/android/launcher3/graphics/ScrimView.java b/src/com/android/launcher3/graphics/ScrimView.java
new file mode 100644
index 0000000..521fbed
--- /dev/null
+++ b/src/com/android/launcher3/graphics/ScrimView.java
@@ -0,0 +1,97 @@
+/*
+ * 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.graphics;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.RectF;
+import android.support.v4.graphics.ColorUtils;
+import android.util.AttributeSet;
+import android.view.View;
+
+import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+
+public class ScrimView extends View {
+
+ // Config
+ private static final int MASK_HEIGHT_DP = 600;
+ private static final float MASK_START_LENGTH_FACTOR = 0.4f;
+ private static final float FINAL_ALPHA = 0.87f;
+ private static final int SCRIM_COLOR = ColorUtils.setAlphaComponent(
+ Color.WHITE, (int) (FINAL_ALPHA * 255));
+
+ private static Bitmap sFinalScrimMask;
+ private static Bitmap sAlphaScrimMask;
+
+ private final int mMaskHeight;
+ private int mVisibleHeight;
+ private final int mHeadStart;
+
+ private final RectF mAlphaMaskRect = new RectF();
+ private final RectF mFinalMaskRect = new RectF();
+ private final Paint mPaint = new Paint();
+ private float mProgress;
+
+ public ScrimView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ mMaskHeight = Utilities.pxFromDp(MASK_HEIGHT_DP, getResources().getDisplayMetrics());
+ mHeadStart = (int) (mMaskHeight * MASK_START_LENGTH_FACTOR);
+ mPaint.setColor(SCRIM_COLOR);
+
+ if (sFinalScrimMask == null) {
+ sFinalScrimMask = Utilities.convertToAlphaMask(
+ Utilities.createOnePixBitmap(), FINAL_ALPHA);
+ }
+ if (sAlphaScrimMask == null) {
+ Bitmap alphaMaskFromResource = BitmapFactory.decodeResource(getResources(),
+ R.drawable.all_apps_alpha_mask);
+ sAlphaScrimMask = Utilities.convertToAlphaMask(alphaMaskFromResource, FINAL_ALPHA);
+ }
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ int width = MeasureSpec.getSize(widthMeasureSpec);
+ mVisibleHeight = MeasureSpec.getSize(heightMeasureSpec);
+ int fullHeight = mVisibleHeight * 2 + mMaskHeight;
+ setMeasuredDimension(width, fullHeight);
+ setProgress(mProgress);
+ }
+
+ public void setProgress(float progress) {
+ mProgress = progress;
+ float initialY = mVisibleHeight - mHeadStart;
+ float fullTranslationY = mMaskHeight + initialY + mVisibleHeight;
+ float translationY = initialY - progress * fullTranslationY;
+ setTranslationY(translationY);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ mAlphaMaskRect.set(0, 0, getWidth(), mMaskHeight);
+ mFinalMaskRect.set(0, mMaskHeight, getWidth(), getHeight());
+ canvas.drawBitmap(sAlphaScrimMask, null, mAlphaMaskRect, mPaint);
+ canvas.drawBitmap(sFinalScrimMask, null, mFinalMaskRect, mPaint);
+ }
+
+}
diff --git a/src/com/android/launcher3/graphics/ShadowGenerator.java b/src/com/android/launcher3/graphics/ShadowGenerator.java
index 469fe34..695015d 100644
--- a/src/com/android/launcher3/graphics/ShadowGenerator.java
+++ b/src/com/android/launcher3/graphics/ShadowGenerator.java
@@ -22,8 +22,10 @@
import android.graphics.BlurMaskFilter;
import android.graphics.BlurMaskFilter.Blur;
import android.graphics.Canvas;
+import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
+import android.support.v4.graphics.ColorUtils;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.util.Preconditions;
@@ -39,9 +41,9 @@
// Percent of actual icon size
private static final float KEY_SHADOW_DISTANCE = 1f/48;
- public static final int KEY_SHADOW_ALPHA = 61;
+ private static final int KEY_SHADOW_ALPHA = 61;
- public static final int AMBIENT_SHADOW_ALPHA = 30;
+ private static final int AMBIENT_SHADOW_ALPHA = 30;
private static final Object LOCK = new Object();
// Singleton object guarded by {@link #LOCK}
@@ -84,45 +86,45 @@
}
public static Bitmap createPillWithShadow(int rectColor, int width, int height) {
-
float shadowRadius = height * 1f / 32;
float shadowYOffset = height * 1f / 16;
+ return createPillWithShadow(rectColor, width, height, shadowRadius, shadowYOffset,
+ new RectF());
+ }
+ public static Bitmap createPillWithShadow(int rectColor, int width, int height,
+ float shadowRadius, float shadowYOffset, RectF outRect) {
int radius = height / 2;
- Canvas canvas = new Canvas();
- Paint blurPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
- blurPaint.setMaskFilter(new BlurMaskFilter(shadowRadius, Blur.NORMAL));
-
int centerX = Math.round(width / 2 + shadowRadius);
int centerY = Math.round(radius + shadowRadius + shadowYOffset);
int center = Math.max(centerX, centerY);
int size = center * 2;
Bitmap result = Bitmap.createBitmap(size, size, Config.ARGB_8888);
- canvas.setBitmap(result);
- int left = center - width / 2;
- int top = center - height / 2;
- int right = center + width / 2;
- int bottom = center + height / 2;
+ outRect.set(0, 0, width, height);
+ outRect.offsetTo(center - width / 2, center - height / 2);
- // Draw ambient shadow, center aligned within size
- blurPaint.setAlpha(AMBIENT_SHADOW_ALPHA);
- canvas.drawRoundRect(left, top, right, bottom, radius, radius, blurPaint);
-
- // Draw key shadow, bottom aligned within size
- blurPaint.setAlpha(KEY_SHADOW_ALPHA);
- canvas.drawRoundRect(left, top + shadowYOffset, right, bottom + shadowYOffset,
- radius, radius, blurPaint);
-
- // Draw the circle
- Paint drawPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
- drawPaint.setColor(rectColor);
- canvas.drawRoundRect(left, top, right, bottom, radius, radius, drawPaint);
-
+ drawShadow(new Canvas(result), outRect, rectColor, shadowRadius, shadowYOffset, radius);
return result;
}
+ public static void drawShadow(Canvas c, RectF bounds, int color,
+ float shadowBlur, float keyShadowDistance, float radius) {
+ Paint p = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
+ p.setColor(color);
+
+ // Key shadow
+ p.setShadowLayer(shadowBlur, 0, keyShadowDistance,
+ ColorUtils.setAlphaComponent(Color.BLACK, KEY_SHADOW_ALPHA));
+ c.drawRoundRect(bounds, radius, radius, p);
+
+ // Ambient shadow
+ p.setShadowLayer(shadowBlur, 0, 0,
+ ColorUtils.setAlphaComponent(Color.BLACK, AMBIENT_SHADOW_ALPHA));
+ c.drawRoundRect(bounds, radius, radius, p);
+ }
+
public static ShadowGenerator getInstance(Context context) {
Preconditions.assertNonUiThread();
synchronized (LOCK) {
diff --git a/src/com/android/launcher3/popup/SystemShortcut.java b/src/com/android/launcher3/popup/SystemShortcut.java
index 6747540..a52d1d4 100644
--- a/src/com/android/launcher3/popup/SystemShortcut.java
+++ b/src/com/android/launcher3/popup/SystemShortcut.java
@@ -1,7 +1,9 @@
package com.android.launcher3.popup;
import android.content.Context;
+import android.graphics.Rect;
import android.graphics.drawable.Drawable;
+import android.os.Bundle;
import android.view.View;
import com.android.launcher3.AbstractFloatingView;
@@ -80,7 +82,9 @@
return new View.OnClickListener() {
@Override
public void onClick(View view) {
- InfoDropTarget.startDetailsActivityForInfo(itemInfo, launcher, null);
+ Rect sourceBounds = launcher.getViewBounds(view);
+ Bundle opts = launcher.getActivityLaunchOptions(view);
+ InfoDropTarget.startDetailsActivityForInfo(itemInfo, launcher, null, sourceBounds, opts);
}
};
}
diff --git a/src_flags/com/android/launcher3/config/FeatureFlags.java b/src_flags/com/android/launcher3/config/FeatureFlags.java
index 159f125..c0184fa 100644
--- a/src_flags/com/android/launcher3/config/FeatureFlags.java
+++ b/src_flags/com/android/launcher3/config/FeatureFlags.java
@@ -38,6 +38,8 @@
public static boolean LAUNCHER3_UPDATE_SOFT_INPUT_MODE = true;
// When enabled the promise icon is visible in all apps while installation an app.
public static boolean LAUNCHER3_PROMISE_APPS_IN_ALL_APPS = true;
+ // When enabled uses the AllAppsRadialGradientAndScrimDrawable for all apps
+ public static boolean LAUNCHER3_GRADIENT_ALL_APPS = false;
// Feature flag to enable moving the QSB on the 0th screen of the workspace.
public static final boolean QSB_ON_FIRST_SCREEN = true;