写在开头
公司老项目决定从ImageLoader替换为当前流行框架Glide,准备单独开发成图片组件,目前正在学习中,总结一波,希望能和大家共同进步,也希望大家提供更好的封装及思路共同完善这个组件,方便你我的使用。
图片组件地址:https://github.com/loveAndroidAndroid/GlideMoudle(包含图片变换,进度监听,图片(gif)加载等等,还希望大家能一起补充)
PS:也掺杂了一个android权限工具类,包含跳转各个手机型号的权限设置页面。也希望大家提出宝贵的意见。
言归正传:开始今天Transformation变换学习之旅。
Glide推荐学习:https://blog.csdn.net/guolin_blog/article/details/53759439
Transformation用来干什么?
平常开发中,我们时常会对网络加载的图片进行处理,比如Glide自带centerCrop(),fitCenter()处理,自定义圆形,圆角,模糊处理等等。
如何学习Transformation?(基于Glide 4.7.1)
首先我们先学习系统自带的Transformation的做法,然后在自定义自己的Transformation。那么就话不多说,我们直接打开CenterCrop类来看一下它的源码吧,如下所示:
public class CenterCrop extends BitmapTransformation {
private static final String ID = "com.bumptech.glide.load.resource.bitmap.CenterCrop";
private static final byte[] ID_BYTES = ID.getBytes(CHARSET);
//实现图形变换,主要是这个方法
@Override
protected Bitmap transform(
@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) {
return TransformationUtils.centerCrop(pool, toTransform, outWidth, outHeight);
}
//重写epquals和hashcode方法,确保对象唯一性,以和其他的图片变换做区分
@Override
public boolean equals(Object o) {
return o instanceof CenterCrop;
}
@Override
public int hashCode() {
return ID.hashCode();
}
//可通过内部算法 重写此方法自定义图片缓存key
@Override
public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) {
messageDigest.update(ID_BYTES);
}
}
复制代码
第一:CenterCrop继承自BitmapTransformation的,这个是必须的。我们自定义Transformation也要继承这个类。因为整个图片变换功能都是建立在这个继承结构基础上的。
第二:图像变换最重要的就是transform()方法,这个是我们自定义Transformation的关键方法,我们的处理逻辑都要在这个方法里实现。transform()方法中有四个参数。 (1)pool,这个是Glide中的BitmapPool缓存池,用于对Bitmap对象进行重用,否则每次图片变换都重新创建Bitmap对象将会非常消耗内存。
(2)toTransform,这个是原始图片的Bitmap对象,我们就是要对它来进行图片变换。
(3)图片变换后的宽度
(4)图片变换后的高度
我们可以看到transform()的处理都在TransformationUtils中,那么我们看一下transform()方法的细节。源码及解释如下:
public static Bitmap centerCrop(@NonNull BitmapPool pool, @NonNull Bitmap inBitmap, int width,
int height) {
//简单校验
if (inBitmap.getWidth() == width && inBitmap.getHeight() == height) {
return inBitmap;
}
// From ImageView/Bitmap.createScaledBitmap.计算画布的缩放的比例以及偏移值
final float scale;
final float dx;
final float dy;
Matrix m = new Matrix();
if (inBitmap.getWidth() * height > width * inBitmap.getHeight()) {
scale = (float) height / (float) inBitmap.getHeight();
dx = (width - inBitmap.getWidth() * scale) * 0.5f;
dy = 0;
} else {
scale = (float) width / (float) inBitmap.getWidth();
dx = 0;
dy = (height - inBitmap.getHeight() * scale) * 0.5f;
}
m.setScale(scale, scale);
m.postTranslate((int) (dx + 0.5f), (int) (dy + 0.5f));
//从Bitmap缓存池中尝试获取一个可重用的Bitmap对象
Bitmap result = pool.get(width, height, getNonNullConfig(inBitmap));
// 将原图Bitmap对象的alpha值复制到裁剪Bitmap对象上面
TransformationUtils.setAlpha(inBitmap, result);
//裁剪Bitmap对象进行绘制,并将最终的结果进行返回
applyMatrix(inBitmap, result, m);
return result;
}
复制代码
对于equals,hashCode,updateDiskCacheKey不太重要,上面源码中也有相应解释,暂不多说。
自定义Transformation实现圆形图片。
/**
* 裁剪图片为圆
*/
public class CircleTransformation extends BitmapTransformation {
private final String TAG = getClass().getName();
@Override
protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) {
//得到图片最小边
int size = Math.min(toTransform.getWidth(), toTransform.getHeight());
//计算图片起点
int x = (toTransform.getWidth() - size) / 2;
int y = (toTransform.getHeight() - size) / 2;
//创建新的bitmaop
Bitmap square = Bitmap.createBitmap(toTransform, x, y, size, size);
//得到glide中BitmapPool的bitmap位图对象
Bitmap circle = pool.get(size, size, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(circle);
Paint paint = new Paint();
//设置TileMode的样式 CLAMP 拉伸 REPEAT 重复 MIRROR 镜像
paint.setShader(new BitmapShader(square, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));
paint.setAntiAlias(true);
float r = size / 2f;
//画圆
canvas.drawCircle(r, r, r, paint);
return circle;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof BlurTransformation) {
return this == obj;
}
return false;
}
@Override
public int hashCode() {
return Util.hashCode(TAG.hashCode());
}
@Override
public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) {
messageDigest.update(TAG.getBytes(CHARSET));
}
}
复制代码
更多变换
在图片组件中我实现了三种自定义变换,包含圆形,圆角和模糊。
网上也有很多Glide的图片变换开源库,我感觉做的最好的是glide-transformations这个库了吧。它实现了很多通用的图片变换效果,如裁剪变换、颜色变换、模糊变换等等,使得我们可以非常轻松地进行各种各样的图片变换。不过我们用不到那么多功能的话也不需要依赖一个三方库了吧,主要还是要学习为主。
三方库项目地址:https://github.com/wasabeef/glide-transformations
写在最后
今天的文章就到这里了,希望大家也学会了。下篇文章中我会写一下关于关于监听Glide进度的文章,顺一下自己的思路,也记录下自己的学习过程。