简介
一直以来,对于图片的圆形显示一直都是一个长生不衰的话题,随着各大图片加载库的进化和替换,加载圆形图片的方法一直都在进步,这里我们梳理一下,虽然现在有现成的开元方案使用,但是我们还是从学习的角度来看看那些自行的实现,还是很考验绘图方面的基础的,这一直都是我们广大 android 的弱项。
方案
其实我们有很多选择来加载圆形图片,这里我列举一下:
- 使用官方实现
- 扩展官方基类 BitmapTransformation
- 开源库 glide-transformations
- 开源库 CircleImageView
官方实现
Glide 的官方实现很简单,也是效果最好的了
GlideApp.with(activity)
.load(url)
// 裁剪成圆形,和系统缓存完美配合
.circleCrop()
.into(imageView);
BitmapTransformation
这个类是 Glide 推出的变换扩展的基类,继承这个类我们可以实现任意的对图片资源的扩展,当然裁剪成圆形也是 OK 的
这里有一个实现,不是很好,因为最后一个方法没有做实现,这是有关图片缓存的。所以会造成一个问题,每次重新加载这个圆形图片资源,因为没有缓存走会走一次解码原始资源,变换裁剪的过程,因为要占用原始资源,所以view 原先显示的这个图片资源就会被清空,而图片重新处理又需要一点点时间,多一造成了 view 会有一下的白屏闪过。
public class GlideCircleTransform extends BitmapTransformation {
public GlideCircleTransform(Context context) {
super(context);
}
@Override
protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
return circleCrop(pool, toTransform);
}
private static Bitmap circleCrop(BitmapPool pool, Bitmap source) {
if (source == null) return null;
int size = Math.min(source.getWidth(), source.getHeight());
int x = (source.getWidth() - size) / 2;
int y = (source.getHeight() - size) / 2;
Bitmap squared = Bitmap.createBitmap(source, x, y, size, size);
Bitmap result = pool.get(size, size, Bitmap.Config.ARGB_8888);
if (result == null) {
result = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
}
Canvas canvas = new Canvas(result);
Paint paint = new Paint();
paint.setShader(new BitmapShader(squared, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));
paint.setAntiAlias(true);
float r = size / 2f;
canvas.drawCircle(r, r, r, paint);
return result;
}
@Override
public void updateDiskCacheKey(MessageDigest messageDigest) {
messageDigest.update(getClass().getName().getBytes());
}
}
开源库 glide-transformations
这个开源库,使用起来也很简单的,地址:glide-transformations
GlideApp.with(activity)
.asBitmap()
.load(url)
.transform(new CropCircleTransformation())
.into(imageView);
// Glide transform
implementation 'jp.wasabeef:glide-transformations:3.0.0'
// If you want to use the GPU Filters
implementation 'jp.co.cyberagent.android.gpuimage:gpuimage-library:1.4.1'
最新是3.1.0版本,但是需要API 27支持,3.0.0 API 26就可以了。
开源库 CircleImageView
这个是经典的圆形图片组件,有很多人都在用,但是这个组件和 Glide 结合起来很麻烦,需要专门自定义 Glide 的 transition 过度动画,和自定义 trageView 才能正常显示,要不然会出现第一次加载不显示,没有过度动画的,问题。我是是在没心情做 CircleImageView 的适配了,有时间做完了再放上吧。
若是想用的话,我们可以声明 Glide 获取的资源类型为 Bitmap,在 into 中自己操作资源,这样可以正常显示,但是无法使用过度动画了。
GlideApp.with(activity)
.asBitmap()
.load(url)
.into(new SimpleTarget<Bitmap>() {
@Override
public void onResourceReady(Bitmap resource, Transition<? super Bitmap> transition) {
imageView.setImageBitmap(resource);
}
});
不推荐用这个开源组件,地址我放上吧,有兴趣的可以去玩玩:CircleImageView
dependencies {
...
compile 'de.hdodenhof:circleimageview:2.2.0'
}
结论
这个使用 Glide 加载圆形图片,除了使用官方实现,其他所有方式都存在无法缓存变换后位图的问题,都会造成一个短暂的白屏。