Android圖片加載框架最全解析(五),Glide強大的圖片變換功能

轉載請註明出處:http://blog.csdn.net/guolin_blog/article/details/71524668

本文同步發表於我的微信公衆號,掃一掃文章底部的二維碼或在微信搜索 郭霖 即可關注,每天都有文章更新。

大家好,又到了學習Glide的時間了。前段時間由於項目開發緊張,再加上後來又生病了,所以停更了一個月,不過現在終於又可以恢復正常更新了。今天是這個系列的第五篇文章,在前面四篇文章的當中,我們已經學習了Glide的基本用法、Glide的工作原理和執行流程、Glide的緩存機制、以及Glide的回調機制等內容。如果你能將前面的四篇文章都掌握好了,那麼恭喜你,現在你已經是一名Glide好手了。

如果你還沒有閱讀過前面四篇文章的話,那麼可以點擊後面的鏈接,依次向前閱讀 Android圖片加載框架最全解析(四),玩轉Glide的回調與監聽

不過Glide的這個框架的功能實在是太強大了,它所能做的事情遠遠不止於目前我們所學的這些。因此,今天我們就再來學習一個新的功能模塊,並且是一個非常重要的模塊——Glide的圖片變化功能。

一個問題

在正式開始學習Glide的圖片變化功能之前,我們先來看一個問題,這個問題可能有不少人都在使用Glide的時候都遇到過,正好在本篇內容的主題之下我們順帶着將這個問題給解決了。

首先我們嘗試使用Glide來加載一張圖片,圖片URL地址是:

https://www.baidu.com/img/bd_logo1.png

這是百度首頁logo的一張圖片,圖片尺寸是540*258像素。

接下來我們編寫一個非常簡單的佈局文件,如下所示:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Load Image"
        android:onClick="loadImage"
        />

    <ImageView
        android:id="@+id/image_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />
</LinearLayout>

佈局文件中只有一個按鈕和一個用於顯示圖片的ImageView。注意,ImageView的寬和高這裏設置的都是wrap_content。

然後編寫如下的代碼來加載圖片:

public class MainActivity extends AppCompatActivity {

    ImageView imageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        imageView = (ImageView) findViewById(R.id.image_view);
    }

    public void loadImage(View view) {
        String url = "https://www.baidu.com/img/bd_logo1.png";
        Glide.with(this)
             .load(url)
             .into(imageView);
    }
}

這些簡單的代碼對於現在的你而言應該都是小兒科了,相信我也不用再做什麼解釋。現在運行一下程序並點擊加載圖片按鈕,效果如下圖所示。

圖片是正常加載出來了,不過大家有沒有發現一個問題。百度這張logo圖片的尺寸只有540*258像素,但是我的手機的分辨率卻是1080*1920像素,而我們將ImageView的寬高設置的都是wrap_content,那麼圖片的寬度應該只有手機屏幕寬度的一半而已,但是這裏卻充滿了全屏,這是爲什麼呢?

如果你之前也被這個問題困擾過,那麼恭喜,本篇文章正是你所需要的。之所以會出現這個現象,就是因爲Glide的圖片變換功能所導致的。那麼接下來我們會先分析如何解決這個問題,然後再深入學習Glide圖片變化的更多功能。

稍微對Android有點了解的人應該都知道ImageView有scaleType這個屬性,但是可能大多數人卻不知道,如果在沒有指定scaleType屬性的情況下,ImageView默認的scaleType是什麼?

這個問題如果直接問我,我也答不上來。不過動手纔是檢驗真理的唯一標準,想知道答案,自己動手試一下就知道了。

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";

    ImageView imageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        imageView = (ImageView) findViewById(R.id.image_view);
        Log.d(TAG, "imageView scaleType is " + imageView.getScaleType());
    }

    ...
}

可以看到,我們在onCreate()方法中打印了ImageView默認的scaleType,然後重新運行一下程序,結果如下圖所示:

由此我們可以得知,在沒有明確指定的情況下,ImageView默認的scaleType是FIT_CENTER。

有了這個前提條件,我們就可以繼續去分析Glide的源碼了。當然,本文中的源碼還是建在第二篇源碼分析的基礎之上,還沒有看過這篇文章的朋友,建議先去閱讀 Android圖片加載框架最全解析(二),從源碼的角度理解Glide的執行流程

回顧一下第二篇文章中我們分析過的into()方法,它是在GenericRequestBuilder類當中的,代碼如下所示:

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));
}

還記得我們當初分析這段代碼的時候,直接跳過前面的所有代碼,直奔最後一行。因爲那個時候我們的主要任務是分析Glide的主線執行流程,而不去仔細閱讀它的細節,但是現在我們是時候應該閱讀一下細節了。

可以看到,這裏在第7行會進行一個switch判斷,如果ImageView的scaleType是CENTER_CROP,則會去調用applyCenterCrop()方法,如果scaleType是FIT_CENTER、FIT_START或FIT_END,則會去調用applyFitCenter()方法。這裏的applyCenterCrop()和applyFitCenter()方法其實就是向Glide的加載流程中添加了一個圖片變換操作,具體的源碼我們就不跟進去看了。

那麼現在我們就基本清楚了,由於ImageView默認的scaleType是FIT_CENTER,因此會自動添加一個FitCenter的圖片變換,而在這個圖片變換過程中做了某些操作,導致圖片充滿了全屏。

那麼我們該如何解決這個問題呢?最直白的一種辦法就是看着源碼來改。當ImageView的scaleType是CENTER_CROP、FIT_CENTER、FIT_START或FIT_END時不是會自動添加一個圖片變換操作嗎?那我們把scaleType改成其他值不就可以了。ImageView的scaleType可選值還有CENTER、CENTER_INSIDE、FIT_XY等。這當然是一種解決方案,不過只能說是一種比較笨的解決方案,因爲我們爲了解決這個問題而去改動了ImageView原有的scaleType,那如果你真的需要ImageView的scaleType爲CENTER_CROP或FIT_CENTER時可能就傻眼了。

上面只是我們通過分析源碼得到的一種解決方案,並不推薦大家使用。實際上,Glide給我們提供了專門的API來添加和取消圖片變換,想要解決這個問題只需要使用如下代碼即可:

Glide.with(this)
     .load(url)
     .dontTransform()
     .into(imageView);

可以看到,這裏調用了一個dontTransform()方法,表示讓Glide在加載圖片的過程中不進行圖片變換,這樣剛纔調用的applyCenterCrop()、applyFitCenter()就統統無效了。

現在我們重新運行一下代碼,效果如下圖所示:

這樣圖片就只會佔據半個屏幕的寬度了,說明我們的代碼奏效了。

但是使用dontTransform()方法存在着一個問題,就是調用這個方法之後,所有的圖片變換操作就全部失效了,那如果我有一些圖片變換操作是必須要執行的該怎麼辦呢?不用擔心,總歸是有辦法的,這種情況下我們只需要藉助override()方法強制將圖片尺寸指定成原始大小就可以了,代碼如下所示:

Glide.with(this)
     .load(url)
     .override(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
     .into(imageView);

通過override()方法將圖片的寬和高都指定成Target.SIZE_ORIGINAL,問題同樣被解決了。程序的最終運行結果和上圖是完全一樣的,我就不再重新截圖了。

由此我們可以看出,之所以會出現這個問題,和Glide的圖片變換功能是撇不開關係的。那麼也是通過這個問題,我們對Glide的圖片變換有了一個最基本的認識。接下來,就讓我們正式開始進入本篇文章的正題吧。

圖片變換的基本用法

顧名思義,圖片變換的意思就是說,Glide從加載了原始圖片到最終展示給用戶之前,又進行了一些變換處理,從而能夠實現一些更加豐富的圖片效果,如圖片圓角化、圓形化、模糊化等等。

添加圖片變換的用法非常簡單,我們只需要調用transform()方法,並將想要執行的圖片變換操作作爲參數傳入transform()方法即可,如下所示:

Glide.with(this)
     .load(url)
     .transform(...)
     .into(imageView);

至於具體要進行什麼樣的圖片變換操作,這個通常都是需要我們自己來寫的。不過Glide已經內置了兩種圖片變換操作,我們可以直接拿來使用,一個是CenterCrop,一個是FitCenter。

但這兩種內置的圖片變換操作其實都不需要使用transform()方法,Glide爲了方便我們使用直接提供了現成的API:

Glide.with(this)
     .load(url)
     .centerCrop()
     .into(imageView);

Glide.with(this)
     .load(url)
     .fitCenter()
     .into(imageView);

當然,centerCrop()和fitCenter()方法其實也只是對transform()方法進行了一層封裝而已,它們背後的源碼仍然還是藉助transform()方法來實現的,如下所示:

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());
    }

    ...
}

那麼這兩種內置的圖片變換操作到底能實現什麼樣的效果呢?FitCenter的效果其實剛纔我們已經見識過了,就是會將圖片按照原始的長寬比充滿全屏。那麼CenterCrop又是什麼樣的效果呢?我們來動手試一下就知道了。

爲了讓效果更加明顯,這裏我就不使用百度首頁的Logo圖了,而是換成必應首頁的一張美圖。在不應用任何圖片變換的情況下,使用Glide加載必應這張圖片效果如下所示。

現在我們添加一個CenterCrop的圖片變換操作,代碼如下:

String url = "http://cn.bing.com/az/hprichbg/rb/AvalancheCreek_ROW11173354624_1920x1080.jpg";
Glide.with(this)
     .load(url)
     .centerCrop()
     .into(imageView);

重新運行一下程序並點擊加載圖片按鈕,效果如下圖所示。

可以看到,現在展示的圖片是對原圖的中心區域進行裁剪後得到的圖片。

另外,centerCrop()方法還可以配合override()方法來實現更加豐富的效果,比如指定圖片裁剪的比例:

String url = "http://cn.bing.com/az/hprichbg/rb/AvalancheCreek_ROW11173354624_1920x1080.jpg";
Glide.with(this)
     .load(url)
     .override(500, 500)
     .centerCrop()
     .into(imageView);

可以看到,這裏我們將圖片的尺寸設定爲500*500像素,那麼裁剪的比例也就變成1:1了,現在重新運行一下程序,效果如下圖所示。

這樣我們就把Glide內置的圖片變換接口的用法都掌握了。不過不得不說,Glide內置的圖片變換接口功能十分單一且有限,完全沒有辦法滿足我們平時的開發需求。因此,掌握自定義圖片變換功能就顯得尤爲重要了。

不過,在正式開始學習自定義圖片變換功能之前,我們先來探究一下CenterCrop這種圖片變換的源碼,理解了它的源碼我們再來進行自定義圖片變換就能更加得心應手了。

源碼分析

那麼就話不多說,我們直接打開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的,這個是重中之重,因爲整個圖片變換功能都是建立在這個繼承結構基礎上的。

接下來CenterCrop中最重要的就是transform()方法,其他的方法我們可以暫時忽略。transform()方法中有四個參數,每一個都很重要,我們來一一解讀下。第一個參數pool,這個是Glide中的一個Bitmap緩存池,用於對Bitmap對象進行重用,否則每次圖片變換都重新創建Bitmap對象將會非常消耗內存。第二個參數toTransform,這個是原始圖片的Bitmap對象,我們就是要對它來進行圖片變換。第三和第四個參數比較簡單,分別代表圖片變換後的寬度和高度,其實也就是override()方法中傳入的寬和高的值了。

下面我們來看一下transform()方法的細節,首先第一行就從Bitmap緩存池中嘗試獲取一個可重用的Bitmap對象,然後把這個對象連同toTransform、outWidth、outHeight參數一起傳入到了TransformationUtils.centerCrop()方法當中。那麼我們就跟進去來看一下這個方法的源碼,如下所示:

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;
    }

    ...
}

這段代碼就是整個圖片變換功能的核心代碼了。可以看到,第5-9行主要是先做了一些校驗,如果原圖爲空,或者原圖的尺寸和目標裁剪尺寸相同,那麼就放棄裁剪。接下來第11-22行是通過數學計算來算出畫布的縮放的比例以及偏移值。第24-29行是判斷緩存池中取出的Bitmap對象是否爲空,如果不爲空就可以直接使用,如果爲空則要創建一個新的Bitmap對象。第32行是將原圖Bitmap對象的alpha值複製到裁剪Bitmap對象上面。最後第34-37行是裁剪Bitmap對象進行繪製,並將最終的結果進行返回。全部的邏輯就是這樣,總體來說還是比較簡單的,可能也就是數學計算那邊需要稍微動下腦筋。

那麼現在得到了裁剪後的Bitmap對象,我們再回到CenterCrop當中,你會看到,在最終返回這個Bitmap對象之前,還會嘗試將複用的Bitmap對象重新放回到緩存池當中,以便下次繼續使用。

好的,這樣我們就將CenterCrop圖片變換的工作原理完整地分析了一遍,FitCenter的源碼也是基本類似的,這裏就不再重複分析了。瞭解了這些內容之後,接下來我們就可以開始學習自定義圖片變換功能了。

自定義圖片變換

Glide給我們定製好了一個圖片變換的框架,大致的流程是我們可以獲取到原始的圖片,然後對圖片進行變換,再將變換完成後的圖片返回給Glide,最終由Glide將圖片顯示出來。理論上,在對圖片進行變換這個步驟中我們可以進行任何的操作,你想對圖片怎麼樣都可以。包括圓角化、圓形化、黑白化、模糊化等等,甚至你將原圖片完全替換成另外一張圖都是可以的。

但是這裏顯然我不可能向大家演示所有圖片變換的可能,圖片變換的可能性也是無限的。因此這裏我們就選擇一種常用的圖片變換效果來進行自定義吧——對圖片進行圓形化變換。

圖片圓形化的功能現在在手機應用中非常常見,比如手機QQ就會將用戶的頭像進行圓形化變換,從而使得界面變得更加好看。

自定義圖片變換功能的實現邏輯比較固定,我們剛纔看過CenterCrop的源碼之後,相信你已經基本瞭解整個自定義的過程了。其實就是自定義一個類讓它繼承自BitmapTransformation ,然後重寫transform()方法,並在這裏去實現具體的圖片變換邏輯就可以了。一個空的圖片變換實現大概如下所示:

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) {
        return null;
    }
}

這裏有一點需要注意,就是getId()方法中要求返回一個唯一的字符串來作爲id,以和其他的圖片變換做區分。通常情況下,我們直接返回當前類的完整類名就可以了。

另外,這裏我們選擇繼承BitmapTransformation還有一個限制,就是隻能對靜態圖進行圖片變換。當然,這已經足夠覆蓋日常95%以上的開發需求了。如果你有特殊的需求要對GIF圖進行圖片變換,那就得去自己實現Transformation接口纔可以了。不過這個就非常複雜了,不在我們今天的討論範圍。

好了,那麼我們繼續實現對圖片進行圓形化變換的功能,接下來只需要在transform()方法中去做具體的邏輯實現就可以了,代碼如下所示:

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;
    }
}

下面我來對transform()方法中的邏輯做下簡單的解釋。首先第18行先算出原圖寬度和高度中較小的值,因爲對圖片進行圓形化變換肯定要以較小的那個值作爲直徑來進行裁剪。第20-26行則和剛纔一樣,從Bitmap緩存池中嘗試獲取一個Bitmap對象來進行重用,如果沒有可重用的Bitmap對象的話就創建一個。第28-41行是具體進行圓形化變換的部分,這裏算出了畫布的偏移值,並且根據剛纔得到的直徑算出半徑來進行畫圓。最後,嘗試將複用的Bitmap對象重新放回到緩存池當中,並將圓形化變換後的Bitmap對象進行返回。

這樣,一個自定義圖片變換的功能就寫好了,那麼現在我們就來嘗試使用一下它吧。使用方法非常簡單,剛纔已經介紹過了,就是把這個自定義圖片變換的實例傳入到transform()方法中即可,如下所示:

Glide.with(this)
     .load(url)
     .transform(new CircleCrop(this))
     .into(imageView);

現在我們重新運行一下程序,效果如下圖所示。

更多圖片變換功能

雖說Glide的圖片變換功能框架已經很強大了,使得我們可以輕鬆地自定義圖片變換效果,但是如果每一種圖片變換都要我們自己去寫還是蠻吃力的。事實上,確實也沒有必要完全靠自己去實現各種各樣的圖片變換效果,因爲大多數的圖片變換都是比較通用的,各個項目會用到的效果都差不多,我們每一個都自己去重新實現無異於重複造輪子。

也正是因此,網上出現了很多Glide的圖片變換開源庫,其中做的最出色的應該要數glide-transformations這個庫了。它實現了很多通用的圖片變換效果,如裁剪變換、顏色變換、模糊變換等等,使得我們可以非常輕鬆地進行各種各樣的圖片變換。

glide-transformations的項目主頁地址是 https://github.com/wasabeef/glide-transformations

下面我們就來體驗一下這個庫的強大功能吧。首先需要將這個庫引入到我們的項目當中,在app/build.gradle文件當中添加如下依賴:

dependencies {
    compile 'jp.wasabeef:glide-transformations:2.0.2'
}

現在如果我想對圖片進行模糊化處理,那麼就可以使用glide-transformations庫中的BlurTransformation這個類,代碼如下所示:

Glide.with(this)
     .load(url)
     .bitmapTransform(new BlurTransformation(this))
     .into(imageView);

注意這裏我們調用的是bitmapTransform()方法而不是transform()方法,因爲glide-transformations庫都是專門針對靜態圖片變換來進行設計的。現在重新運行一下程度,效果如下圖所示。

沒錯,我們就這樣輕鬆地實現模糊化的效果了。

接下來我們再試一下圖片黑白化的效果,使用的是GrayscaleTransformation這個類,代碼如下所示:

Glide.with(this)
     .load(url)
     .bitmapTransform(new GrayscaleTransformation(this))
     .into(imageView);

現在重新運行一下程度,效果如下圖所示。

而且我們還可以將多個圖片變換效果組合在一起使用,比如同時執行模糊化和黑白化的變換:

Glide.with(this)
     .load(url)
     .bitmapTransform(new BlurTransformation(this), new GrayscaleTransformation(this))
     .into(imageView);

可以看到,同時執行多種圖片變換的時候,只需要將它們都傳入到bitmapTransform()方法中即可。現在重新運行一下程序,效果如下圖所示。

當然,這些只是glide-transformations庫的一小部分功能而已,更多的圖片變換效果你可以到它的GitHub項目主頁去學習,所有變換的用法都是這麼簡單哦。

好了,那麼今天的文章就到這裏了,相信大家的收穫都很多吧。下篇文章中我們會繼續深入探究Glide,學習一下自定義模塊的功能,感興趣的朋友請繼續閱讀 Android圖片加載框架最全解析(六),探究Glide的自定義模塊功能

關注我的技術公衆號,每天都有優質技術文章推送。關注我的娛樂公衆號,工作、學習累了的時候放鬆一下自己。

微信掃一掃下方二維碼即可關注:

        

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章