Remove launcher dependency inside LauncherIcons
Bug: 115891474 Change-Id: Ie05d005ee3f8a10ebae35f8cf72b4f255a305667
This commit is contained in:
parent
2ccdd08ad1
commit
b8137d0e00
|
@ -0,0 +1,303 @@
|
|||
package com.android.launcher3.icons;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.PaintFlagsDrawFilter;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.drawable.AdaptiveIconDrawable;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.os.Process;
|
||||
import android.os.UserHandle;
|
||||
|
||||
import com.android.launcher3.R;
|
||||
|
||||
import static android.graphics.Paint.DITHER_FLAG;
|
||||
import static android.graphics.Paint.FILTER_BITMAP_FLAG;
|
||||
import static com.android.launcher3.icons.ShadowGenerator.BLUR_FACTOR;
|
||||
|
||||
/**
|
||||
* This class will be moved to androidx library. There shouldn't be any dependency outside
|
||||
* this package.
|
||||
*/
|
||||
public class BaseIconFactory {
|
||||
|
||||
private static final int DEFAULT_WRAPPER_BACKGROUND = Color.WHITE;
|
||||
public static final boolean ATLEAST_OREO = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
|
||||
|
||||
private final Rect mOldBounds = new Rect();
|
||||
private final Context mContext;
|
||||
private final Canvas mCanvas;
|
||||
private final PackageManager mPm;
|
||||
private final ColorExtractor mColorExtractor;
|
||||
private boolean mDisableColorExtractor;
|
||||
|
||||
private int mFillResIconDpi;
|
||||
private int mIconBitmapSize;
|
||||
|
||||
private IconNormalizer mNormalizer;
|
||||
private ShadowGenerator mShadowGenerator;
|
||||
|
||||
private Drawable mWrapperIcon;
|
||||
private int mWrapperBackgroundColor;
|
||||
|
||||
protected BaseIconFactory(Context context, int fillResIconDpi, int iconBitmapSize) {
|
||||
mContext = context.getApplicationContext();
|
||||
|
||||
mFillResIconDpi = fillResIconDpi;
|
||||
mIconBitmapSize = iconBitmapSize;
|
||||
|
||||
mPm = mContext.getPackageManager();
|
||||
mColorExtractor = new ColorExtractor();
|
||||
|
||||
mCanvas = new Canvas();
|
||||
mCanvas.setDrawFilter(new PaintFlagsDrawFilter(DITHER_FLAG, FILTER_BITMAP_FLAG));
|
||||
}
|
||||
|
||||
protected void clear() {
|
||||
mWrapperBackgroundColor = DEFAULT_WRAPPER_BACKGROUND;
|
||||
mDisableColorExtractor = false;
|
||||
}
|
||||
|
||||
public ShadowGenerator getShadowGenerator() {
|
||||
if (mShadowGenerator == null) {
|
||||
mShadowGenerator = new ShadowGenerator(mContext);
|
||||
}
|
||||
return mShadowGenerator;
|
||||
}
|
||||
|
||||
public IconNormalizer getNormalizer() {
|
||||
if (mNormalizer == null) {
|
||||
mNormalizer = new IconNormalizer(mContext);
|
||||
}
|
||||
return mNormalizer;
|
||||
}
|
||||
|
||||
public BitmapInfo createIconBitmap(Intent.ShortcutIconResource iconRes) {
|
||||
try {
|
||||
Resources resources = mPm.getResourcesForApplication(iconRes.packageName);
|
||||
if (resources != null) {
|
||||
final int id = resources.getIdentifier(iconRes.resourceName, null, null);
|
||||
// do not stamp old legacy shortcuts as the app may have already forgotten about it
|
||||
return createBadgedIconBitmap(
|
||||
resources.getDrawableForDensity(id, mFillResIconDpi),
|
||||
Process.myUserHandle() /* only available on primary user */,
|
||||
false /* do not apply legacy treatment */);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Icon not found.
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public BitmapInfo createIconBitmap(Bitmap icon) {
|
||||
if (mIconBitmapSize == icon.getWidth() && mIconBitmapSize == icon.getHeight()) {
|
||||
return BitmapInfo.fromBitmap(icon);
|
||||
}
|
||||
return BitmapInfo.fromBitmap(
|
||||
createIconBitmap(new BitmapDrawable(mContext.getResources(), icon), 1f));
|
||||
}
|
||||
|
||||
public BitmapInfo createBadgedIconBitmap(Drawable icon, UserHandle user,
|
||||
boolean shrinkNonAdaptiveIcons) {
|
||||
return createBadgedIconBitmap(icon, user, shrinkNonAdaptiveIcons, false, null);
|
||||
}
|
||||
|
||||
public BitmapInfo createBadgedIconBitmap(Drawable icon, UserHandle user,
|
||||
boolean shrinkNonAdaptiveIcons, boolean isInstantApp) {
|
||||
return createBadgedIconBitmap(icon, user, shrinkNonAdaptiveIcons, isInstantApp, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates bitmap using the source drawable and various parameters.
|
||||
* The bitmap is visually normalized with other icons and has enough spacing to add shadow.
|
||||
*
|
||||
* @param icon source of the icon
|
||||
* @param user info can be used for a badge
|
||||
* @param shrinkNonAdaptiveIcons {@code true} if non adaptive icons should be treated
|
||||
* @param isInstantApp info can be used for a badge
|
||||
* @param scale returns the scale result from normalization
|
||||
* @return a bitmap suitable for disaplaying as an icon at various system UIs.
|
||||
*/
|
||||
public BitmapInfo createBadgedIconBitmap(Drawable icon, UserHandle user,
|
||||
boolean shrinkNonAdaptiveIcons, boolean isInstantApp, float[] scale) {
|
||||
if (scale == null) {
|
||||
scale = new float[1];
|
||||
}
|
||||
icon = normalizeAndWrapToAdaptiveIcon(icon, shrinkNonAdaptiveIcons, null, scale);
|
||||
Bitmap bitmap = createIconBitmap(icon, scale[0]);
|
||||
if (ATLEAST_OREO && icon instanceof AdaptiveIconDrawable) {
|
||||
mCanvas.setBitmap(bitmap);
|
||||
getShadowGenerator().recreateIcon(Bitmap.createBitmap(bitmap), mCanvas);
|
||||
mCanvas.setBitmap(null);
|
||||
}
|
||||
|
||||
final Bitmap result;
|
||||
if (user != null && !Process.myUserHandle().equals(user)) {
|
||||
BitmapDrawable drawable = new FixedSizeBitmapDrawable(bitmap);
|
||||
Drawable badged = mPm.getUserBadgedIcon(drawable, user);
|
||||
if (badged instanceof BitmapDrawable) {
|
||||
result = ((BitmapDrawable) badged).getBitmap();
|
||||
} else {
|
||||
result = createIconBitmap(badged, 1f);
|
||||
}
|
||||
} else if (isInstantApp) {
|
||||
badgeWithDrawable(bitmap, mContext.getDrawable(R.drawable.ic_instant_app_badge));
|
||||
result = bitmap;
|
||||
} else {
|
||||
result = bitmap;
|
||||
}
|
||||
return BitmapInfo.fromBitmap(result, mDisableColorExtractor ? null : mColorExtractor);
|
||||
}
|
||||
|
||||
public Bitmap createScaledBitmapWithoutShadow(Drawable icon, boolean shrinkNonAdaptiveIcons) {
|
||||
RectF iconBounds = new RectF();
|
||||
float[] scale = new float[1];
|
||||
icon = normalizeAndWrapToAdaptiveIcon(icon, shrinkNonAdaptiveIcons, iconBounds, scale);
|
||||
return createIconBitmap(icon,
|
||||
Math.min(scale[0], ShadowGenerator.getScaleForBounds(iconBounds)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the background color used for wrapped adaptive icon
|
||||
*/
|
||||
public void setWrapperBackgroundColor(int color) {
|
||||
mWrapperBackgroundColor = (Color.alpha(color) < 255) ? DEFAULT_WRAPPER_BACKGROUND : color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the dominant color extraction for all icons loaded.
|
||||
*/
|
||||
public void disableColorExtraction() {
|
||||
mDisableColorExtractor = true;
|
||||
}
|
||||
|
||||
private Drawable normalizeAndWrapToAdaptiveIcon(Drawable icon, boolean shrinkNonAdaptiveIcons,
|
||||
RectF outIconBounds, float[] outScale) {
|
||||
float scale = 1f;
|
||||
|
||||
if (shrinkNonAdaptiveIcons) {
|
||||
boolean[] outShape = new boolean[1];
|
||||
if (mWrapperIcon == null) {
|
||||
mWrapperIcon = mContext.getDrawable(R.drawable.adaptive_icon_drawable_wrapper)
|
||||
.mutate();
|
||||
}
|
||||
AdaptiveIconDrawable dr = (AdaptiveIconDrawable) mWrapperIcon;
|
||||
dr.setBounds(0, 0, 1, 1);
|
||||
scale = getNormalizer().getScale(icon, outIconBounds, dr.getIconMask(), outShape);
|
||||
if (ATLEAST_OREO && !outShape[0] && !(icon instanceof AdaptiveIconDrawable)) {
|
||||
FixedScaleDrawable fsd = ((FixedScaleDrawable) dr.getForeground());
|
||||
fsd.setDrawable(icon);
|
||||
fsd.setScale(scale);
|
||||
icon = dr;
|
||||
scale = getNormalizer().getScale(icon, outIconBounds, null, null);
|
||||
|
||||
((ColorDrawable) dr.getBackground()).setColor(mWrapperBackgroundColor);
|
||||
}
|
||||
} else {
|
||||
scale = getNormalizer().getScale(icon, outIconBounds, null, null);
|
||||
}
|
||||
|
||||
outScale[0] = scale;
|
||||
return icon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the {@param badge} on top of {@param target} using the badge dimensions.
|
||||
*/
|
||||
public void badgeWithDrawable(Bitmap target, Drawable badge) {
|
||||
mCanvas.setBitmap(target);
|
||||
badgeWithDrawable(mCanvas, badge);
|
||||
mCanvas.setBitmap(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the {@param badge} on top of {@param target} using the badge dimensions.
|
||||
*/
|
||||
public void badgeWithDrawable(Canvas target, Drawable badge) {
|
||||
int badgeSize = mContext.getResources().getDimensionPixelSize(R.dimen.profile_badge_size);
|
||||
badge.setBounds(mIconBitmapSize - badgeSize, mIconBitmapSize - badgeSize,
|
||||
mIconBitmapSize, mIconBitmapSize);
|
||||
badge.draw(target);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param scale the scale to apply before drawing {@param icon} on the canvas
|
||||
*/
|
||||
private Bitmap createIconBitmap(Drawable icon, float scale) {
|
||||
Bitmap bitmap = Bitmap.createBitmap(mIconBitmapSize, mIconBitmapSize,
|
||||
Bitmap.Config.ARGB_8888);
|
||||
mCanvas.setBitmap(bitmap);
|
||||
mOldBounds.set(icon.getBounds());
|
||||
|
||||
if (ATLEAST_OREO && icon instanceof AdaptiveIconDrawable) {
|
||||
int offset = Math.max((int) Math.ceil(BLUR_FACTOR * mIconBitmapSize),
|
||||
Math.round(mIconBitmapSize * (1 - scale) / 2 ));
|
||||
icon.setBounds(offset, offset, mIconBitmapSize - offset, mIconBitmapSize - offset);
|
||||
icon.draw(mCanvas);
|
||||
} else {
|
||||
if (icon instanceof BitmapDrawable) {
|
||||
BitmapDrawable bitmapDrawable = (BitmapDrawable) icon;
|
||||
Bitmap b = bitmapDrawable.getBitmap();
|
||||
if (bitmap != null && b.getDensity() == Bitmap.DENSITY_NONE) {
|
||||
bitmapDrawable.setTargetDensity(mContext.getResources().getDisplayMetrics());
|
||||
}
|
||||
}
|
||||
int width = mIconBitmapSize;
|
||||
int height = mIconBitmapSize;
|
||||
|
||||
int intrinsicWidth = icon.getIntrinsicWidth();
|
||||
int intrinsicHeight = icon.getIntrinsicHeight();
|
||||
if (intrinsicWidth > 0 && intrinsicHeight > 0) {
|
||||
// Scale the icon proportionally to the icon dimensions
|
||||
final float ratio = (float) intrinsicWidth / intrinsicHeight;
|
||||
if (intrinsicWidth > intrinsicHeight) {
|
||||
height = (int) (width / ratio);
|
||||
} else if (intrinsicHeight > intrinsicWidth) {
|
||||
width = (int) (height * ratio);
|
||||
}
|
||||
}
|
||||
final int left = (mIconBitmapSize - width) / 2;
|
||||
final int top = (mIconBitmapSize - height) / 2;
|
||||
icon.setBounds(left, top, left + width, top + height);
|
||||
mCanvas.save();
|
||||
mCanvas.scale(scale, scale, mIconBitmapSize / 2, mIconBitmapSize / 2);
|
||||
icon.draw(mCanvas);
|
||||
mCanvas.restore();
|
||||
|
||||
}
|
||||
icon.setBounds(mOldBounds);
|
||||
mCanvas.setBitmap(null);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
/**
|
||||
* An extension of {@link BitmapDrawable} which returns the bitmap pixel size as intrinsic size.
|
||||
* This allows the badging to be done based on the action bitmap size rather than
|
||||
* the scaled bitmap size.
|
||||
*/
|
||||
private static class FixedSizeBitmapDrawable extends BitmapDrawable {
|
||||
|
||||
public FixedSizeBitmapDrawable(Bitmap bitmap) {
|
||||
super(null, bitmap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntrinsicHeight() {
|
||||
return getBitmap().getWidth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntrinsicWidth() {
|
||||
return getBitmap().getWidth();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,29 +16,11 @@
|
|||
|
||||
package com.android.launcher3.icons;
|
||||
|
||||
import static android.graphics.Paint.DITHER_FLAG;
|
||||
import static android.graphics.Paint.FILTER_BITMAP_FLAG;
|
||||
|
||||
import static com.android.launcher3.icons.ShadowGenerator.BLUR_FACTOR;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.Intent.ShortcutIconResource;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PaintFlagsDrawFilter;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.drawable.AdaptiveIconDrawable;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.PaintDrawable;
|
||||
import android.os.Build;
|
||||
import android.os.Process;
|
||||
import android.os.UserHandle;
|
||||
|
@ -49,7 +31,6 @@ import com.android.launcher3.graphics.BitmapRenderer;
|
|||
import com.android.launcher3.InvariantDeviceProfile;
|
||||
import com.android.launcher3.ItemInfoWithIcon;
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.model.PackageItemInfo;
|
||||
import com.android.launcher3.shortcuts.DeepShortcutManager;
|
||||
|
@ -60,14 +41,14 @@ import com.android.launcher3.util.Themes;
|
|||
import androidx.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Helper methods for generating various launcher icons
|
||||
* Wrapper class to provide access to {@link BaseIconFactory} and also to provide pool of this class
|
||||
* that are threadsafe.
|
||||
*/
|
||||
public class LauncherIcons implements AutoCloseable {
|
||||
public class LauncherIcons extends BaseIconFactory implements AutoCloseable {
|
||||
|
||||
private static final int DEFAULT_WRAPPER_BACKGROUND = Color.WHITE;
|
||||
|
||||
public static final Object sPoolSync = new Object();
|
||||
private static final Object sPoolSync = new Object();
|
||||
private static LauncherIcons sPool;
|
||||
private LauncherIcons next;
|
||||
|
||||
/**
|
||||
* Return a new Message instance from the global pool. Allows us to
|
||||
|
@ -82,7 +63,8 @@ public class LauncherIcons implements AutoCloseable {
|
|||
return m;
|
||||
}
|
||||
}
|
||||
return new LauncherIcons(context);
|
||||
InvariantDeviceProfile idp = LauncherAppState.getIDP(context);
|
||||
return new LauncherIcons(context, idp.fillResIconDpi, idp.iconBitmapSize);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -91,8 +73,7 @@ public class LauncherIcons implements AutoCloseable {
|
|||
public void recycle() {
|
||||
synchronized (sPoolSync) {
|
||||
// Clear any temporary state variables
|
||||
mWrapperBackgroundColor = DEFAULT_WRAPPER_BACKGROUND;
|
||||
mDisableColorExtractor = false;
|
||||
clear();
|
||||
|
||||
next = sPool;
|
||||
sPool = this;
|
||||
|
@ -104,259 +85,41 @@ public class LauncherIcons implements AutoCloseable {
|
|||
recycle();
|
||||
}
|
||||
|
||||
private final Rect mOldBounds = new Rect();
|
||||
private final Context mContext;
|
||||
private final Canvas mCanvas;
|
||||
private final PackageManager mPm;
|
||||
private final ColorExtractor mColorExtractor;
|
||||
private boolean mDisableColorExtractor;
|
||||
|
||||
private final int mFillResIconDpi;
|
||||
private final int mIconBitmapSize;
|
||||
|
||||
private IconNormalizer mNormalizer;
|
||||
private ShadowGenerator mShadowGenerator;
|
||||
|
||||
private Drawable mWrapperIcon;
|
||||
private int mWrapperBackgroundColor = DEFAULT_WRAPPER_BACKGROUND;
|
||||
|
||||
// sometimes we store linked lists of these things
|
||||
private LauncherIcons next;
|
||||
|
||||
private LauncherIcons(Context context) {
|
||||
private LauncherIcons(Context context, int fillResIconDpi, int iconBitmapSize) {
|
||||
super(context, fillResIconDpi, iconBitmapSize);
|
||||
mContext = context.getApplicationContext();
|
||||
mPm = mContext.getPackageManager();
|
||||
mColorExtractor = new ColorExtractor();
|
||||
|
||||
InvariantDeviceProfile idp = LauncherAppState.getIDP(mContext);
|
||||
mFillResIconDpi = idp.fillResIconDpi;
|
||||
mIconBitmapSize = idp.iconBitmapSize;
|
||||
|
||||
mCanvas = new Canvas();
|
||||
mCanvas.setDrawFilter(new PaintFlagsDrawFilter(DITHER_FLAG, FILTER_BITMAP_FLAG));
|
||||
mFillResIconDpi = fillResIconDpi;
|
||||
mIconBitmapSize = iconBitmapSize;
|
||||
}
|
||||
|
||||
public ShadowGenerator getShadowGenerator() {
|
||||
if (mShadowGenerator == null) {
|
||||
mShadowGenerator = new ShadowGenerator(mContext);
|
||||
}
|
||||
return mShadowGenerator;
|
||||
public BitmapInfo createBadgedIconBitmap(Drawable icon, UserHandle user,
|
||||
int iconAppTargetSdk) {
|
||||
return createBadgedIconBitmap(icon, user, iconAppTargetSdk, false);
|
||||
}
|
||||
|
||||
public IconNormalizer getNormalizer() {
|
||||
if (mNormalizer == null) {
|
||||
mNormalizer = new IconNormalizer(mContext);
|
||||
}
|
||||
return mNormalizer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a bitmap suitable for the all apps view. If the package or the resource do not
|
||||
* exist, it returns null.
|
||||
*/
|
||||
public BitmapInfo createIconBitmap(ShortcutIconResource iconRes) {
|
||||
try {
|
||||
Resources resources = mPm.getResourcesForApplication(iconRes.packageName);
|
||||
if (resources != null) {
|
||||
final int id = resources.getIdentifier(iconRes.resourceName, null, null);
|
||||
// do not stamp old legacy shortcuts as the app may have already forgotten about it
|
||||
return createBadgedIconBitmap(
|
||||
resources.getDrawableForDensity(id, mFillResIconDpi),
|
||||
Process.myUserHandle() /* only available on primary user */,
|
||||
0 /* do not apply legacy treatment */);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Icon not found.
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a bitmap which is of the appropriate size to be displayed as an icon
|
||||
*/
|
||||
public BitmapInfo createIconBitmap(Bitmap icon) {
|
||||
if (mIconBitmapSize == icon.getWidth() && mIconBitmapSize == icon.getHeight()) {
|
||||
return BitmapInfo.fromBitmap(icon);
|
||||
}
|
||||
return BitmapInfo.fromBitmap(
|
||||
createIconBitmap(new BitmapDrawable(mContext.getResources(), icon), 1f));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a bitmap suitable for displaying as an icon at various launcher UIs like all apps
|
||||
* view or workspace. The icon is badged for {@param user}.
|
||||
* The bitmap is also visually normalized with other icons.
|
||||
*/
|
||||
public BitmapInfo createBadgedIconBitmap(Drawable icon, UserHandle user, int iconAppTargetSdk) {
|
||||
return createBadgedIconBitmap(icon, user, iconAppTargetSdk, false, null);
|
||||
}
|
||||
|
||||
public BitmapInfo createBadgedIconBitmap(Drawable icon, UserHandle user, int iconAppTargetSdk,
|
||||
boolean isInstantApp) {
|
||||
public BitmapInfo createBadgedIconBitmap(Drawable icon, UserHandle user,
|
||||
int iconAppTargetSdk, boolean isInstantApp) {
|
||||
return createBadgedIconBitmap(icon, user, iconAppTargetSdk, isInstantApp, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a bitmap suitable for displaying as an icon at various launcher UIs like all apps
|
||||
* view or workspace. The icon is badged for {@param user}.
|
||||
* The bitmap is also visually normalized with other icons.
|
||||
*/
|
||||
public BitmapInfo createBadgedIconBitmap(Drawable icon, UserHandle user, int iconAppTargetSdk,
|
||||
boolean isInstantApp, float[] scale) {
|
||||
if (scale == null) {
|
||||
scale = new float[1];
|
||||
}
|
||||
icon = normalizeAndWrapToAdaptiveIcon(icon, iconAppTargetSdk, null, scale);
|
||||
Bitmap bitmap = createIconBitmap(icon, scale[0]);
|
||||
if (Utilities.ATLEAST_OREO && icon instanceof AdaptiveIconDrawable) {
|
||||
mCanvas.setBitmap(bitmap);
|
||||
getShadowGenerator().recreateIcon(Bitmap.createBitmap(bitmap), mCanvas);
|
||||
mCanvas.setBitmap(null);
|
||||
}
|
||||
|
||||
final Bitmap result;
|
||||
if (user != null && !Process.myUserHandle().equals(user)) {
|
||||
BitmapDrawable drawable = new FixedSizeBitmapDrawable(bitmap);
|
||||
Drawable badged = mPm.getUserBadgedIcon(drawable, user);
|
||||
if (badged instanceof BitmapDrawable) {
|
||||
result = ((BitmapDrawable) badged).getBitmap();
|
||||
} else {
|
||||
result = createIconBitmap(badged, 1f);
|
||||
}
|
||||
} else if (isInstantApp) {
|
||||
badgeWithDrawable(bitmap, mContext.getDrawable(R.drawable.ic_instant_app_badge));
|
||||
result = bitmap;
|
||||
} else {
|
||||
result = bitmap;
|
||||
}
|
||||
return BitmapInfo.fromBitmap(result, mDisableColorExtractor ? null : mColorExtractor);
|
||||
public BitmapInfo createBadgedIconBitmap(Drawable icon, UserHandle user,
|
||||
int iconAppTargetSdk, boolean isInstantApp, float[] scale) {
|
||||
boolean shrinkNonAdaptiveIcons = Utilities.ATLEAST_P ||
|
||||
(Utilities.ATLEAST_OREO && iconAppTargetSdk >= Build.VERSION_CODES.O);
|
||||
return createBadgedIconBitmap(icon, user, shrinkNonAdaptiveIcons, isInstantApp, scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a normalized bitmap suitable for the all apps view. The bitmap is also visually
|
||||
* normalized with other icons and has enough spacing to add shadow.
|
||||
*/
|
||||
public Bitmap createScaledBitmapWithoutShadow(Drawable icon, int iconAppTargetSdk) {
|
||||
RectF iconBounds = new RectF();
|
||||
float[] scale = new float[1];
|
||||
icon = normalizeAndWrapToAdaptiveIcon(icon, iconAppTargetSdk, iconBounds, scale);
|
||||
return createIconBitmap(icon,
|
||||
Math.min(scale[0], ShadowGenerator.getScaleForBounds(iconBounds)));
|
||||
boolean shrinkNonAdaptiveIcons = Utilities.ATLEAST_P ||
|
||||
(Utilities.ATLEAST_OREO && iconAppTargetSdk >= Build.VERSION_CODES.O);
|
||||
return createScaledBitmapWithoutShadow(icon, shrinkNonAdaptiveIcons);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the background color used for wrapped adaptive icon
|
||||
*/
|
||||
public void setWrapperBackgroundColor(int color) {
|
||||
mWrapperBackgroundColor = (Color.alpha(color) < 255) ? DEFAULT_WRAPPER_BACKGROUND : color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the dominant color extraction for all icons loaded through this session (until
|
||||
* this instance is recycled).
|
||||
*/
|
||||
public void disableColorExtraction() {
|
||||
mDisableColorExtractor = true;
|
||||
}
|
||||
|
||||
private Drawable normalizeAndWrapToAdaptiveIcon(Drawable icon, int iconAppTargetSdk,
|
||||
RectF outIconBounds, float[] outScale) {
|
||||
float scale = 1f;
|
||||
if ((Utilities.ATLEAST_OREO && iconAppTargetSdk >= Build.VERSION_CODES.O) ||
|
||||
Utilities.ATLEAST_P) {
|
||||
boolean[] outShape = new boolean[1];
|
||||
if (mWrapperIcon == null) {
|
||||
mWrapperIcon = mContext.getDrawable(R.drawable.adaptive_icon_drawable_wrapper)
|
||||
.mutate();
|
||||
}
|
||||
AdaptiveIconDrawable dr = (AdaptiveIconDrawable) mWrapperIcon;
|
||||
dr.setBounds(0, 0, 1, 1);
|
||||
scale = getNormalizer().getScale(icon, outIconBounds, dr.getIconMask(), outShape);
|
||||
if (Utilities.ATLEAST_OREO && !outShape[0] && !(icon instanceof AdaptiveIconDrawable)) {
|
||||
FixedScaleDrawable fsd = ((FixedScaleDrawable) dr.getForeground());
|
||||
fsd.setDrawable(icon);
|
||||
fsd.setScale(scale);
|
||||
icon = dr;
|
||||
scale = getNormalizer().getScale(icon, outIconBounds, null, null);
|
||||
|
||||
((ColorDrawable) dr.getBackground()).setColor(mWrapperBackgroundColor);
|
||||
}
|
||||
} else {
|
||||
scale = getNormalizer().getScale(icon, outIconBounds, null, null);
|
||||
}
|
||||
|
||||
outScale[0] = scale;
|
||||
return icon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the {@param badge} on top of {@param target} using the badge dimensions.
|
||||
*/
|
||||
public void badgeWithDrawable(Bitmap target, Drawable badge) {
|
||||
mCanvas.setBitmap(target);
|
||||
badgeWithDrawable(mCanvas, badge);
|
||||
mCanvas.setBitmap(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the {@param badge} on top of {@param target} using the badge dimensions.
|
||||
*/
|
||||
private void badgeWithDrawable(Canvas target, Drawable badge) {
|
||||
int badgeSize = mContext.getResources().getDimensionPixelSize(R.dimen.profile_badge_size);
|
||||
badge.setBounds(mIconBitmapSize - badgeSize, mIconBitmapSize - badgeSize,
|
||||
mIconBitmapSize, mIconBitmapSize);
|
||||
badge.draw(target);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param scale the scale to apply before drawing {@param icon} on the canvas
|
||||
*/
|
||||
private Bitmap createIconBitmap(Drawable icon, float scale) {
|
||||
Bitmap bitmap = Bitmap.createBitmap(mIconBitmapSize, mIconBitmapSize,
|
||||
Bitmap.Config.ARGB_8888);
|
||||
mCanvas.setBitmap(bitmap);
|
||||
mOldBounds.set(icon.getBounds());
|
||||
|
||||
if (Utilities.ATLEAST_OREO && icon instanceof AdaptiveIconDrawable) {
|
||||
int offset = Math.max((int) Math.ceil(BLUR_FACTOR * mIconBitmapSize),
|
||||
Math.round(mIconBitmapSize * (1 - scale) / 2 ));
|
||||
icon.setBounds(offset, offset, mIconBitmapSize - offset, mIconBitmapSize - offset);
|
||||
icon.draw(mCanvas);
|
||||
} else {
|
||||
if (icon instanceof BitmapDrawable) {
|
||||
BitmapDrawable bitmapDrawable = (BitmapDrawable) icon;
|
||||
Bitmap b = bitmapDrawable.getBitmap();
|
||||
if (bitmap != null && b.getDensity() == Bitmap.DENSITY_NONE) {
|
||||
bitmapDrawable.setTargetDensity(mContext.getResources().getDisplayMetrics());
|
||||
}
|
||||
}
|
||||
int width = mIconBitmapSize;
|
||||
int height = mIconBitmapSize;
|
||||
|
||||
int intrinsicWidth = icon.getIntrinsicWidth();
|
||||
int intrinsicHeight = icon.getIntrinsicHeight();
|
||||
if (intrinsicWidth > 0 && intrinsicHeight > 0) {
|
||||
// Scale the icon proportionally to the icon dimensions
|
||||
final float ratio = (float) intrinsicWidth / intrinsicHeight;
|
||||
if (intrinsicWidth > intrinsicHeight) {
|
||||
height = (int) (width / ratio);
|
||||
} else if (intrinsicHeight > intrinsicWidth) {
|
||||
width = (int) (height * ratio);
|
||||
}
|
||||
}
|
||||
final int left = (mIconBitmapSize - width) / 2;
|
||||
final int top = (mIconBitmapSize - height) / 2;
|
||||
icon.setBounds(left, top, left + width, top + height);
|
||||
mCanvas.save();
|
||||
mCanvas.scale(scale, scale, mIconBitmapSize / 2, mIconBitmapSize / 2);
|
||||
icon.draw(mCanvas);
|
||||
mCanvas.restore();
|
||||
|
||||
}
|
||||
icon.setBounds(mOldBounds);
|
||||
mCanvas.setBitmap(null);
|
||||
return bitmap;
|
||||
}
|
||||
// below methods should also migrate to BaseIconFactory
|
||||
|
||||
public BitmapInfo createShortcutIcon(ShortcutInfoCompat shortcutInfo) {
|
||||
return createShortcutIcon(shortcutInfo, true /* badged */);
|
||||
|
@ -424,26 +187,4 @@ public class LauncherIcons implements AutoCloseable {
|
|||
return pkgInfo;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An extension of {@link BitmapDrawable} which returns the bitmap pixel size as intrinsic size.
|
||||
* This allows the badging to be done based on the action bitmap size rather than
|
||||
* the scaled bitmap size.
|
||||
*/
|
||||
private static class FixedSizeBitmapDrawable extends BitmapDrawable {
|
||||
|
||||
public FixedSizeBitmapDrawable(Bitmap bitmap) {
|
||||
super(null, bitmap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntrinsicHeight() {
|
||||
return getBitmap().getWidth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntrinsicWidth() {
|
||||
return getBitmap().getWidth();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue