簡介
一直以來,對于圖片的圓形顯示一直都是一個長生不衰的話題,隨著各大圖片加載庫的進化和替換,加載圓形圖片的方法一直都在進步,這里我們梳理一下,雖然現在有現成的開元方案使用,但是我們還是從學習的角度來看看那些自行的實現,還是很考驗繪圖方面的基礎的,這一直都是我們廣大 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 加載圓形圖片,除了使用官方實現,其他所有方式都存在無法緩存變換后位圖的問題,都會造成一個短暫的白屏。