OSDN Git Service

Add LauncherIcons.AdaptiveIconDrawableWithShadow class to support shadow
authorHyunyoung Song <hyunyoungs@google.com>
Mon, 13 Mar 2017 08:23:15 +0000 (01:23 -0700)
committerHyunyoung Song <hyunyoungs@google.com>
Thu, 16 Mar 2017 20:51:28 +0000 (13:51 -0700)
b/36088922

Test: Settings app
This utility class can be used to bake shadow in drawable level in
system ui surfaces such as Settings, Overview and ShareSheet.

Change-Id: Iaec867d9ce5b949380c1e5004b68269d1bbeacd4

core/java/android/util/LauncherIcons.java [new file with mode: 0644]
graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java

diff --git a/core/java/android/util/LauncherIcons.java b/core/java/android/util/LauncherIcons.java
new file mode 100644 (file)
index 0000000..e5aa2b5
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * 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 android.util;
+
+import android.content.Context;
+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;
+import android.graphics.PaintFlagsDrawFilter;
+import android.graphics.Path;
+import android.graphics.RectF;
+import android.graphics.drawable.AdaptiveIconDrawable;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+
+/**
+ * Utility class to handle icon treatments (e.g., shadow generation) for the Launcher icons.
+ * @hide
+ */
+public final class LauncherIcons {
+
+    private final Paint mPaint = new Paint();
+    private final Canvas mCanvas = new Canvas();
+
+    private static final int KEY_SHADOW_ALPHA = 61;
+    private static final int AMBIENT_SHADOW_ALPHA = 30;
+    private static final float BLUR_FACTOR = 0.5f / 48;
+    private int mShadowInset;
+    private Bitmap mShadowBitmap;
+    private int mIconSize;
+    private Resources mRes;
+
+    public LauncherIcons(Context context) {
+        mRes = context.getResources();
+        DisplayMetrics metrics = mRes.getDisplayMetrics();
+        mShadowInset = (int) metrics.density / DisplayMetrics.DENSITY_DEFAULT;
+        mCanvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.DITHER_FLAG,
+            Paint.FILTER_BITMAP_FLAG));
+        mIconSize = (int) mRes.getDimensionPixelSize(android.R.dimen.app_icon_size);
+    }
+
+    /**
+     * Draw the drawable into a bitmap.
+     */
+    public Bitmap createIconBitmap(Drawable icon) {
+        final Bitmap bitmap = Bitmap.createBitmap(mIconSize, mIconSize, Bitmap.Config.ARGB_8888);
+        mPaint.setAlpha(255);
+        mCanvas.setBitmap(bitmap);
+        int iconInset = 0;
+        if (mShadowBitmap != null) {
+            mCanvas.drawBitmap(mShadowBitmap, 0, 0, mPaint);
+            iconInset = mShadowInset;
+        }
+
+        icon.setBounds(iconInset, iconInset, mIconSize - iconInset,
+            mIconSize - iconInset);
+        icon.draw(mCanvas);
+        mCanvas.setBitmap(null);
+        return bitmap;
+    }
+
+    public Drawable wrapIconDrawableWithShadow(Drawable drawable) {
+        if (!(drawable instanceof AdaptiveIconDrawable)) {
+            return drawable;
+        }
+        AdaptiveIconDrawable d =
+            (AdaptiveIconDrawable) drawable.getConstantState().newDrawable().mutate();
+        getShadowBitmap(d);
+        Bitmap iconbitmap = createIconBitmap(d);
+        return new BitmapDrawable(mRes, iconbitmap);
+    }
+
+    private Bitmap getShadowBitmap(AdaptiveIconDrawable d) {
+        if (mShadowBitmap != null) {
+            return mShadowBitmap;
+        }
+
+        int shadowSize = mIconSize - mShadowInset;
+        mShadowBitmap = Bitmap.createBitmap(mIconSize, mIconSize, Bitmap.Config.ALPHA_8);
+        mCanvas.setBitmap(mShadowBitmap);
+
+        // Draw key shadow
+        mPaint.setColor(Color.TRANSPARENT);
+        float blur = BLUR_FACTOR * mIconSize;
+        mPaint.setShadowLayer(blur, 0, mShadowInset, KEY_SHADOW_ALPHA << 24);
+        d.setBounds(mShadowInset, mShadowInset, mIconSize - mShadowInset, mIconSize - mShadowInset);
+        mCanvas.drawPath(d.getIconMask(), mPaint);
+
+        // Draw ambient shadow
+        mPaint.setShadowLayer(blur, 0, 0, AMBIENT_SHADOW_ALPHA << 24);
+        d.setBounds(mShadowInset, 2 * mShadowInset, mIconSize - mShadowInset, mIconSize);
+        mCanvas.drawPath(d.getIconMask(), mPaint);
+        mPaint.clearShadowLayer();
+
+        return mShadowBitmap;
+    }
+}
index 0722c18..c6c9271 100644 (file)
@@ -218,6 +218,8 @@ public class AdaptiveIconDrawable extends Drawable implements Drawable.Callback
     }
 
     /**
+     * Only call this method after bound is set on this drawable.
+     *
      * @return the mask path object used to clip the drawable
      */
     public Path getIconMask() {
index 47468ae..ac24e2e 100644 (file)
@@ -67,6 +67,7 @@ import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
 import android.util.ArraySet;
+import android.util.LauncherIcons;
 import android.util.Log;
 import android.util.MutableBoolean;
 import android.view.Display;
@@ -142,6 +143,7 @@ public class SystemServicesProxy {
     int mDummyThumbnailHeight;
     Paint mBgProtectionPaint;
     Canvas mBgProtectionCanvas;
+    LauncherIcons mLauncherIcons;
 
     private final Handler mHandler = new H();
 
@@ -299,6 +301,7 @@ public class SystemServicesProxy {
             Collections.addAll(sRecentsBlacklist,
                     res.getStringArray(R.array.recents_blacklist_array));
         }
+        mLauncherIcons = new LauncherIcons(context);
     }
 
     /**
@@ -834,7 +837,7 @@ public class SystemServicesProxy {
             return new ColorDrawable(0xFF666666);
         }
 
-        Drawable icon = info.loadIcon(mPm);
+        Drawable icon = mLauncherIcons.wrapIconDrawableWithShadow(info.loadIcon(mPm));
         return getBadgedIcon(icon, userId);
     }
 
@@ -850,7 +853,7 @@ public class SystemServicesProxy {
             return new ColorDrawable(0xFF666666);
         }
 
-        Drawable icon = appInfo.loadIcon(mPm);
+        Drawable icon = mLauncherIcons.wrapIconDrawableWithShadow(appInfo.loadIcon(mPm));
         return getBadgedIcon(icon, userId);
     }