??首先,默認(rèn)情況下,ImageView的scaleType類型為FIT_CENTER.(scaleType有八種類型:FIT_XY,MATRIX,CENTER,CENTER_CROP,CENTER_INSIDE,FIT_START,FIT_CENTER,FIT_END)
??進入主題,當(dāng)Glide的into方法中的參數(shù)為ImageView的時候,Glide默認(rèn)會進行哪些圖形變換呢?
??我們可以查看into方法的源碼,它是在GenericRequestBuilder類當(dāng)中的,
public Target<TranscodeType> into(ImageView view) {
Util.assertMainThread();
if (view == null) {
throw new IllegalArgumentException("You must pass in a non null View");
}
if (!isTransformationSet && view.getScaleType() != null) {
switch (view.getScaleType()) {
case CENTER_CROP:
applyCenterCrop();
break;
case FIT_CENTER:
case FIT_START:
case FIT_END:
applyFitCenter();
break;
//$CASES-OMITTED$
default:
// Do nothing.
}
}
return into(glide.buildImageViewTarget(view, transcodeClass));
}
??那么現(xiàn)在我們就基本清楚了,由于ImageView默認(rèn)的scaleType是FIT_CENTER,因此會自動添加一個FitCenter的圖片變換,而在這個圖片變換過程中做了某些操作,導(dǎo)致圖片充滿了全屏。
??那我們應(yīng)該如何取消Glide自帶的圖形變換呢?實際上,Glide給我們提供了專門的API來添加和取消圖片變換,想要解決這個問題只需要使用如下代碼即可:
Glide.with(this)
.load(url)
.dontTransform()
.into(imageView);
??可以看到,這里調(diào)用了一個dontTransform()方法,表示讓Glide在加載圖片的過程中不進行圖片變換,這樣剛才調(diào)用的applyCenterCrop()、applyFitCenter()就統(tǒng)統(tǒng)無效了。
??但是使用dontTransform()方法存在著一個問題,就是調(diào)用這個方法之后,所有的圖片變換操作就全部失效了,那如果我有一些圖片變換操作是必須要執(zhí)行的該怎么辦呢?不用擔(dān)心,總歸是有辦法的,這種情況下我們只需要借助override()方法強制將圖片尺寸指定成原始大小就可以了,代碼如下所示:
Glide.with(this)
.load(url)
.override(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
.into(imageView);
圖形變換的基本用法
??顧名思義,圖片變換的意思就是說,Glide從加載了原始圖片到最終展示給用戶之前,又進行了一些變換處理,從而能夠?qū)崿F(xiàn)一些更加豐富的圖片效果,如圖片圓角化、圓形化、模糊化等等。
??添加圖片變換的用法非常簡單,我們只需要調(diào)用transform()方法,并將想要執(zhí)行的圖片變換操作作為參數(shù)傳入transform()方法即可,如下所示:
Glide.with(this)
.load(url)
.transform(...)
.into(imageView);
至于具體要進行什么樣的圖片變換操作,這個通常都是需要我們自己來寫的。不過Glide已經(jīng)內(nèi)置了兩種圖片變換操作,我們可以直接拿來使用,一個是CenterCrop,一個是FitCenter。
但這兩種內(nèi)置的圖片變換操作其實都不需要使用transform()方法,Glide為了方便我們使用直接提供了現(xiàn)成的API:
Glide.with(this)
.load(url)
.centerCrop()
.into(imageView);
Glide.with(this)
.load(url)
.fitCenter()
.into(imageView);
當(dāng)然,centerCrop()和fitCenter()方法其實也只是對transform()方法進行了一層封裝而已,它們背后的源碼仍然還是借助transform()方法來實現(xiàn)的,如下所示:
public class DrawableRequestBuilder<ModelType>
extends GenericRequestBuilder<ModelType, ImageVideoWrapper, GifBitmapWrapper, GlideDrawable>
implements BitmapOptions, DrawableOptions {
...
/**
* Transform {@link GlideDrawable}s using {@link com.bumptech.glide.load.resource.bitmap.CenterCrop}.
*
* @see #fitCenter()
* @see #transform(BitmapTransformation...)
* @see #bitmapTransform(Transformation[])
* @see #transform(Transformation[])
*
* @return This request builder.
*/
@SuppressWarnings("unchecked")
public DrawableRequestBuilder<ModelType> centerCrop() {
return transform(glide.getDrawableCenterCrop());
}
/**
* Transform {@link GlideDrawable}s using {@link com.bumptech.glide.load.resource.bitmap.FitCenter}.
*
* @see #centerCrop()
* @see #transform(BitmapTransformation...)
* @see #bitmapTransform(Transformation[])
* @see #transform(Transformation[])
*
* @return This request builder.
*/
@SuppressWarnings("unchecked")
public DrawableRequestBuilder<ModelType> fitCenter() {
return transform(glide.getDrawableFitCenter());
}
...
}
自定義圖片變換
先看一下centerCrop的源碼
public class CenterCrop extends BitmapTransformation {
public CenterCrop(Context context) {
super(context);
}
public CenterCrop(BitmapPool bitmapPool) {
super(bitmapPool);
}
// Bitmap doesn't implement equals, so == and .equals are equivalent here.
@SuppressWarnings("PMD.CompareObjectsWithEquals")
@Override
protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
final Bitmap toReuse = pool.get(outWidth, outHeight, toTransform.getConfig() != null
? toTransform.getConfig() : Bitmap.Config.ARGB_8888);
Bitmap transformed = TransformationUtils.centerCrop(toReuse, toTransform, outWidth, outHeight);
if (toReuse != null && toReuse != transformed && !pool.put(toReuse)) {
toReuse.recycle();
}
return transformed;
}
@Override
public String getId() {
return "CenterCrop.com.bumptech.glide.load.resource.bitmap";
}
}
??首先,CenterCrop是繼承自BitmapTransformation的,這個是重中之重,因為整個圖片變換功能都是建立在這個繼承結(jié)構(gòu)基礎(chǔ)上的。
??接下來CenterCrop中最重要的就是transform()方法,其他的方法我們可以暫時忽略。transform()方法中有四個參數(shù),每一個都很重要,我們來一一解讀下。第一個參數(shù)pool,這個是Glide中的一個Bitmap緩存池,用于對Bitmap對象進行重用,否則每次圖片變換都重新創(chuàng)建Bitmap對象將會非常消耗內(nèi)存。第二個參數(shù)toTransform,這個是原始圖片的Bitmap對象,我們就是要對它來進行圖片變換。第三和第四個參數(shù)比較簡單,分別代表圖片變換后的寬度和高度,其實也就是override()方法中傳入的寬和高的值了。
??下面我們來看一下transform()方法的細(xì)節(jié),首先第一行就從Bitmap緩存池中嘗試獲取一個可重用的Bitmap對象,然后把這個對象連同toTransform、outWidth、outHeight參數(shù)一起傳入到了TransformationUtils.centerCrop()方法當(dāng)中。那么我們就跟進去來看一下這個方法的源碼,如下所示:
public final class TransformationUtils {
...
public static Bitmap centerCrop(Bitmap recycled, Bitmap toCrop, int width, int height) {
if (toCrop == null) {
return null;
} else if (toCrop.getWidth() == width && toCrop.getHeight() == height) {
return toCrop;
}
// From ImageView/Bitmap.createScaledBitmap.
final float scale;
float dx = 0, dy = 0;
Matrix m = new Matrix();
if (toCrop.getWidth() * height > width * toCrop.getHeight()) {
scale = (float) height / (float) toCrop.getHeight();
dx = (width - toCrop.getWidth() * scale) * 0.5f;
} else {
scale = (float) width / (float) toCrop.getWidth();
dy = (height - toCrop.getHeight() * scale) * 0.5f;
}
m.setScale(scale, scale);
m.postTranslate((int) (dx + 0.5f), (int) (dy + 0.5f));
final Bitmap result;
if (recycled != null) {
result = recycled;
} else {
result = Bitmap.createBitmap(width, height, getSafeConfig(toCrop));
}
// We don't add or remove alpha, so keep the alpha setting of the Bitmap we were given.
TransformationUtils.setAlpha(toCrop, result);
Canvas canvas = new Canvas(result);
Paint paint = new Paint(PAINT_FLAGS);
canvas.drawBitmap(toCrop, m, paint);
return result;
}
...
}
自定義圖片變換之圖片圓形化
包括圓角化、圓形化、黑白化、模糊化等等,甚至你將原圖片完全替換成另外一張圖都是可以的
public class CircleCrop extends BitmapTransformation {
public CircleCrop(Context context) {
super(context);
}
public CircleCrop(BitmapPool bitmapPool) {
super(bitmapPool);
}
@Override
public String getId() {
return "com.example.glidetest.CircleCrop";
}
@Override
protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
int diameter = Math.min(toTransform.getWidth(), toTransform.getHeight());
final Bitmap toReuse = pool.get(outWidth, outHeight, Bitmap.Config.ARGB_8888);
final Bitmap result;
if (toReuse != null) {
result = toReuse;
} else {
result = Bitmap.createBitmap(diameter, diameter, Bitmap.Config.ARGB_8888);
}
int dx = (toTransform.getWidth() - diameter) / 2;
int dy = (toTransform.getHeight() - diameter) / 2;
Canvas canvas = new Canvas(result);
Paint paint = new Paint();
BitmapShader shader = new BitmapShader(toTransform, BitmapShader.TileMode.CLAMP,
BitmapShader.TileMode.CLAMP);
if (dx != 0 || dy != 0) {
Matrix matrix = new Matrix();
matrix.setTranslate(-dx, -dy);
shader.setLocalMatrix(matrix);
}
paint.setShader(shader);
paint.setAntiAlias(true);
float radius = diameter / 2f;
canvas.drawCircle(radius, radius, radius, paint);
if (toReuse != null && !pool.put(toReuse)) {
toReuse.recycle();
}
return result;
}
}
使用CircleCrop
Glide.with(this)
.load(url)
.transform(new CircleCrop(this))
.into(imageView);
自定義圖片開源庫
glide-transformations
(version:3.1.1)實現(xiàn)的transformation有Crop,Color,Blur,Mask