前言
我们平时在使用ImageView,当设置宽高为wrap_content的时候,设置bitmap,有没有想过一个问题,那就是大小究竟是如何计算的,平时说的那些density又和最终显示的图片大小有什么关系呢。本着严谨的态度,我开始了探索源码解读的不归路上。
过程
本次实验所用测试机density为420。我们首先来解码一张bitmap(ic_launcher大小为144 * 144),代码如下:
val options = BitmapFactory.Options()
val bitmap = BitmapFactory.decodeResource(resources, R.mipmap.ic_launcher, options)
Log.d("Bitmap", "{height: ${bitmap.height} --- width: ${bitmap.width}}")
打印结果是{height: 126 — width: 126},那么这个数值是怎么来的呢。我们进入decodeResource一看究竟,
public static Bitmap decodeResource(Resources res, int id, Options opts) {
validate(opts);
Bitmap bm = null;
InputStream is = null;
try {
final TypedValue value = new TypedValue();
is = res.openRawResource(id, value);
bm = decodeResourceStream(res, value, is, null, opts);
} catch (Exception e) {
/* do nothing.
If the exception happened on open, bm will be null.
If it happened on close, bm is still valid.
*/
} finally {
try {
if (is != null) is.close();
} catch (IOException e) {
// Ignore
}
}
if (bm == null && opts != null && opts.inBitmap != null) {
throw new IllegalArgumentException("Problem decoding into existing bitmap");
}
return bm;
}
bitmap是decodeResourceStream产生的,那我们接着往下看,
@Nullable
public static Bitmap decodeResourceStream(@Nullable Resources res, @Nullable TypedValue value,
@Nullable InputStream is, @Nullable Rect pad, @Nullable Options opts) {
validate(opts);
if (opts == null) {
opts = new Options();
}
if (opts.inDensity == 0 && value != null) {
final int density = value.density;
if (density == TypedValue.DENSITY_DEFAULT) {
opts.inDensity = DisplayMetrics.DENSITY_DEFAULT;
} else if (density != TypedValue.DENSITY_NONE) {
opts.inDensity = density;
}
}
if (opts.inTargetDensity == 0 && res != null) {
opts.inTargetDensity = res.getDisplayMetrics().densityDpi;
}
return decodeStream(is, pad, opts);
}
可以看到,如果options.inDensity等于0,这里会对options做赋值操作,inDensity指的是图片资源所在资源