自从 Android 系统引入自适应图标,创建快捷方式的时,就多了一个可以设置的方法,即 IconCompat
里的 createWithAdaptiveBitmap
方法,而在此之前,为快捷方式设置图标位图的方法仅是 createWithBitmap
。
根据对自适应图标的认知,它应该是分为前景和背景两层的,但是上述的新旧两个方法,却都是只接收一个参数。难道一个类型为 Bitmap
的参数是可以容纳两块图像的吗?由此好奇,只好先看一下 createWithAdaptiveBitmap
方法的实现:
1 2 3 4 5 6 7 8 |
public static IconCompat createWithAdaptiveBitmap(Bitmap bits) { if (bits == null) { throw new IllegalArgumentException("Bitmap must not be null."); } final IconCompat rep = new IconCompat(TYPE_ADAPTIVE_BITMAP); rep.mObj1 = bits; return rep; } |
并未看出端倪,只不过是在新建对象时指定了相应的类型而已。由于 IconCompat
仅是系统 Icon
类的浅封装,所以还是要继续看。果不其然,在 toIcon
方法中,对于 TYPE_ADAPTIVE_BITMAP
类型,如果判断系统支持,则会调用 Icon.createWithAdaptiveBitmap
方法。接下来要去系统源码里看了,我看的是线上的:aospxref.com 站点。
在 Icon 类的内部,可以找到一个叫 loadDrawableInner
的方法,可以看到它是如何分别把对应于非自适应的传统图标和自适应图标的位图转换为 Drawable
对象的。节略如下:
1 2 3 4 5 6 7 8 |
private Drawable loadDrawableInner(Context context) { switch (mType) { case TYPE_BITMAP: return new BitmapDrawable(context.getResources(), getBitmap()); case TYPE_ADAPTIVE_BITMAP: return new AdaptiveIconDrawable(null, new BitmapDrawable(context.getResources(), getBitmap())); ... |
可见,位图被传递到了 AdaptiveIconDrawable
对象中,而构建该对象时,构造函数中的第一个参数——通过查看其原型可知——应该是用来指定其背景 Drawable
对象的,被设置为了 null
。
由上可知,Android 系统在传递自适应图标的图像时,采取了一种很不周到的方案,可以说是违背了其设计初衷。正确的方式,哪怕不想在所有的相关方法中增加一个单独的参数用于设置背景,至少也应该将这唯一的 Bitmap 对象进行一种变通改造,使其宽度或者高度倍增(显然是高度更为适宜),将背景一并容纳在内,由接收方收到后进行必要的尺寸检查,然后将该位图再拆为前景和背景两个部分进行绘制。