Glide是 Google推薦的圖片加載庫,它可以支持來自url,Android資源,文件,Uri中的圖片加載,同時還支持gif圖片的加載,以及各種圖片顯示前的bitmap處理(例如:圓角圖片,圓形圖片,高斯模糊,旋轉,灰度等等),緩存處理,請求優先級處理,動畫處理,縮略圖處理,圖片大小自定義等等.可謂是非常的強大.
需要在build.gradle中加入依賴,目前最新的版本是3.7.0,Glide庫地址
compile 'com.github.bumptech.glide:glide:3.7.0'1Created by YWH on2017/2/9
. */public class TestGlideActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test); Uri uri = Uri.parse("android.resource://" + this.getPackageName() + "/" + R.drawable.test); ImageView targetView = (ImageView) findViewById(R.id.iv_target); Glide.with(this). load(uri). asBitmap(). into(targetView); }}12345678910111213141516效果圖:
另外,crossFade還可以接收一個參數來設置淡入顯示效果的持續時間,crossFade(int duration); 如果你想直接顯示圖片,而不是淡入顯示圖片,則可以通過dontAnimate()方法設置.
CenterCrop,FitCenter都是對目標圖片進行裁剪,了解過ImageView的ScaleType屬性就知道,這2種裁剪方式在ImageView上也是有的,分別對應ImageView的ImageView.ScaleType.CENTER_CROP和mageView.ScaleType.FIT_CENTER的.
public class TestGlideActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test); ImageView targetView = (ImageView) findViewById(R.id.iv_target); targetView.setScaleType(ImageView.ScaleType.FIT_CENTER); Glide.with(this). load(R.drawable.test). placeholder(R.drawable.bg_loading).//加載中顯示的圖片 error(R.drawable.bg_error).//加載失敗時顯示的圖片 crossFade(1000).//淡入淡出,注意:如果設置了這個,則必須要去掉asBitmap override(80,80).//設置最終顯示的圖片像素為80*80,注意:這個是像素,而不是控件的寬高 centerCrop().//中心裁剪,縮放填充至整個ImageView into(targetView); }}12345678910111213141516171819內存緩存設置,通過skipMemoryCache(boolean)來設置是否需要緩存到內存,默認是會緩存到內存的.
/** * Created by YWH on2017/2/9 */public class TestGlideActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test); ImageView targetView = (ImageView) findViewById(R.id.iv_target); targetView.setScaleType(ImageView.ScaleType.FIT_CENTER); Glide.with(this). load(R.drawable.test). placeholder(R.drawable.bg_loading).//加載中顯示的圖片 error(R.drawable.bg_error).//加載失敗時顯示的圖片 crossFade(1000).//淡入淡出,注意:如果設置了這個,則必須要去掉asBitmap override(80,80).//設置最終顯示的圖片像素為80*80,注意:這個是像素,而不是控件的寬高 centerCrop().//中心裁剪,縮放填充至整個ImageView skipMemoryCache(true).//跳過內存緩存 into(targetView); }}123456789101112131415161718192021磁盤緩存,磁盤緩存通過diskCacheStrategy(DiskCacheStrategy)來設置,DiskCacheStrategy一共有4種模式:
DiskCacheStrategy.NONE:什么都不緩存 DiskCacheStrategy.SOURCE:僅緩存原圖(全分辨率的圖片)DiskCacheStrategy.RESULT:僅緩存最終的圖片,即修改了尺寸或者轉換后的圖片DiskCacheStrategy.ALL:緩存所有版本的圖片,默認模式public class TestGlideActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test); ImageView targetView = (ImageView) findViewById(R.id.iv_target); targetView.setScaleType(ImageView.ScaleType.FIT_CENTER); Glide.with(this). load(R.drawable.test). placeholder(R.drawable.bg_loading).//加載中顯示的圖片 error(R.drawable.bg_error).//加載失敗時顯示的圖片 crossFade(1000).//淡入淡出,注意:如果設置了這個,則必須要去掉asBitmap override(80, 80).//設置最終顯示的圖片像素為80*80,注意:這個是像素,而不是控件的寬高 centerCrop().//中心裁剪,縮放填充至整個ImageView skipMemoryCache(true).//跳過內存緩存 diskCacheStrategy(DiskCacheStrategy.RESULT).//保存最終圖片 into(targetView); }}1234567891011121314151617181920在GlideModule 中,我們可以設置磁盤緩存的位置,磁盤緩存的大小和內存緩存的大小,同時還可以設置圖片的顯示質量.
要是用GlideModule ,需要創建它的實現類,然后在manifests中申明實現類的全類路徑:
<meta-data android:name="com.example.mchenys.httputilsdemo.image.glide.module.SimpleGlideModule" android:value="GlideModule" />123GlideModule 的實現類,需要實現applyOptions方法:
/** * 所以你知道要創建一個額外的類去定制 Glide。 * 下一步是要全局的去聲明這個類,讓 Glide 知道它應該在哪里被加載和使用。 * Glide 會掃描 AndroidManifest.xml 為 Glide module 的 meta 聲明。 * 因此,你必須在 AndroidManifest.xml 的 <application> 標簽內去聲明這個SimpleGlideModule。 * Created by YWH on2017/2/9 */public class SimpleGlideModule implements GlideModule { public static DiskCache cache; @Override public void applyOptions(Context context, GlideBuilder builder) { // 在 Android 中有兩個主要的方法對圖片進行解碼:ARGB8888 和 RGB565。前者為每個像素使用了 4 個字節, // 后者僅為每個像素使用了 2 個字節。ARGB8888 的優勢是圖像質量更高以及能存儲一個 alpha 通道。 // Picasso 使用 ARGB8888,Glide 默認使用低質量的 RGB565。 // 對于 Glide 使用者來說:你使用 Glide module 方法去改變解碼規則。 builder.setDecodeFormat(DecodeFormat.PREFER_ARGB_8888); //設置緩存目錄 File cacheDir = PathUtils.getDiskCacheDir(context, CacheConfig.IMG_DIR); cache = DiskLruCacheWrapper.get(cacheDir, DiskCache.Factory.DEFAULT_DISK_CACHE_SIZE);// 250 MB builder.setDiskCache(new DiskCache.Factory() { @Override public DiskCache build() { return cache; } }); //設置memory和Bitmap池的大小 MemorySizeCalculator calculator = new MemorySizeCalculator(context); int defaultMemoryCacheSize = calculator.getMemoryCacheSize(); int defaultBitmapPoolSize = calculator.getBitmapPoolSize(); int customMemoryCacheSize = (int) (1.2 * defaultMemoryCacheSize); int customBitmapPoolSize = (int) (1.2 * defaultBitmapPoolSize); builder.setMemoryCache(new LruResourceCache(customMemoryCacheSize)); builder.setBitmapPool(new LruBitmapPool(customBitmapPoolSize)); } @Override public void registerComponents(Context context, Glide glide) { }}12345678910111213141516171819202122232425262728293031323334353637383940414243Glide 可以用 Priority 枚舉來設置圖片的加載優先級,這樣我們就可以針對那些需要顯示的圖片設置高的優先級了. Priority 有4種級別: Priority.LOW Priority.NORMAL Priority.HIGH Priority.IMMEDIATE 例如:
/** * 高優先級加載 * @param url * @param imageView * @param listener */ public static void loadImageWithHighPriority(Object url,ImageView imageView, final LoaderListener listener) { if (url == null) { if (listener != null) { listener.onError(); } } else { Glide.with(imageView.getContext()). load(url). asBitmap(). priority(Priority.HIGH).//高優先級 dontAnimate(). listener(new RequestListener<Object, Bitmap>() { @Override public boolean onException(Exception e, Object model, Target<Bitmap> target, boolean isFirstResource) { if (null != listener) { listener.onError(); } return false; } @Override public boolean onResourceReady(Bitmap resource, Object model, Target<Bitmap> target, boolean isFromMemoryCache, boolean isFirstResource) { if (null != listener) { listener.onSuccess(); } return false; } }).into(imageView); } }123456789101112131415161718192021222324252627282930313233343536通過設置縮略圖,我們可以在顯示目標圖片之前先展示一個第分辨率或者其他圖片,當全分辨率的目標圖片在后臺加載完成后, Glide會自動切換顯示全像素的目標圖片.
設置縮略圖有2種方式: 通過thumbnail(float)指定0.0f~1.0f的原始圖像大小,例如全像素的大小是500*500,如果設置為thumbnail為0.1f,即目標圖片的10%,顯示的縮略圖大小就是50*50;
public class TestGlideActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test); ImageView targetView = (ImageView) findViewById(R.id.iv_target); Glide.with(this). load(R.drawable.test). placeholder(R.drawable.bg_loading).//加載中顯示的圖片 error(R.drawable.bg_error).//加載失敗時顯示的圖片 crossFade(1000).//淡入淡出,注意:如果設置了這個,則必須要去掉asBitmap override(80, 80).//設置最終顯示的圖片像素為80*80,注意:這個是像素,而不是控件的寬高 centerCrop().//中心裁剪,縮放填充至整個ImageView skipMemoryCache(true).//跳過內存緩存 diskCacheStrategy(DiskCacheStrategy.RESULT).//保存最終圖片 thumbnail(0.1f).//10%的原圖大小 into(targetView); }}123456789101112131415161718192021通過thumbnail(DrawableRequestBuilder)方式來指定縮略圖,該縮略圖可以使用load的所有方式(網絡,文件,uri,資源)加載.
public class TestGlideActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test); ImageView targetView = (ImageView) findViewById(R.id.iv_target); //縮略圖請求 DrawableRequestBuilder<String> thumbnailRequest = Glide .with(this) .load("http://www.qq745.com/uploads/allimg/141106/1-141106153Q5.png"); Glide.with(this). load(R.drawable.test).// placeholder(R.drawable.bg_loading).//加載中顯示的圖片// error(R.drawable.bg_error).//加載失敗時顯示的圖片// crossFade(1000).//淡入淡出,注意:如果設置了這個,則必須要去掉asBitmap override(80, 80).//設置最終顯示的圖片像素為80*80,注意:這個是像素,而不是控件的寬高 centerCrop().//中心裁剪,縮放填充至整個ImageView skipMemoryCache(true).//跳過內存緩存 diskCacheStrategy(DiskCacheStrategy.RESULT).//保存最終圖片 thumbnail(thumbnailRequest).//設置縮略圖 into(targetView); }}12345678910111213141516171819202122232425在顯示目標圖片之前,我們可以對目標圖片的Bitmap進行相應的處理,例如::圓角圖片,圓形圖片,高斯模糊,旋轉,灰度等等. 只需要實現Transformation接口即可,該接口的transform方法會返回顯示圖片前的Bitmap對象,在該方法中對 Bitmap的任何處理,都會影響到最終的顯示結果. 當然,如果你只是想要對圖片做常規的 bitmap 轉換,你可以繼承抽象類BitmapTransformation,它簡化了Transformation接口的實現,這應該能覆蓋大部分的應用場景了。
使用的時候,通過transform(Transformation… transformations)來設置.例如:
public class TestGlideActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test); ImageView targetView = (ImageView) findViewById(R.id.iv_target); Glide.with(this). load(R.drawable.test). asBitmap(). transform(new BlurTransformation(this)).//高斯模糊處理 into(targetView); }}12345678910111213下面貼出常用的幾個Bitmap的轉換處理的代碼,在github上也有glide-transformations-master庫.
網上提供的FastBlur,可兼容低版本的高斯模糊處理
public class FastBlur { public static Bitmap blur(Bitmap sentBitmap, int radius, boolean canReuseInBitmap) { Bitmap bitmap; if (canReuseInBitmap) { bitmap = sentBitmap; } else { bitmap = sentBitmap.copy(sentBitmap.getConfig(), true); } if (radius < 1) { return (null); } int w = bitmap.getWidth(); int h = bitmap.getHeight(); int[] pix = new int[w * h]; bitmap.getPixels(pix, 0, w, 0, 0, w, h); int wm = w - 1; int hm = h - 1; int wh = w * h; int div = radius + radius + 1; int r[] = new int[wh]; int g[] = new int[wh]; int b[] = new int[wh]; int rsum, gsum, bsum, x, y, i, p, yp, yi, yw; int vmin[] = new int[Math.max(w, h)]; int divsum = (div + 1) >> 1; divsum *= divsum; int dv[] = new int[256 * divsum]; for (i = 0; i < 256 * divsum; i++) { dv[i] = (i / divsum); } yw = yi = 0; int[][] stack = new int[div][3]; int stackpointer; int stackstart; int[] sir; int rbs; int r1 = radius + 1; int routsum, goutsum, boutsum; int rinsum, ginsum, binsum; for (y = 0; y < h; y++) { rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0; for (i = -radius; i <= radius; i++) { p = pix[yi + Math.min(wm, Math.max(i, 0))]; sir = stack[i + radius]; sir[0] = (p & 0xff0000) >> 16; sir[1] = (p & 0x00ff00) >> 8; sir[2] = (p & 0x0000ff); rbs = r1 - Math.abs(i); rsum += sir[0] * rbs; gsum += sir[1] * rbs; bsum += sir[2] * rbs; if (i > 0) { rinsum += sir[0]; ginsum += sir[1]; binsum += sir[2]; } else { routsum += sir[0]; goutsum += sir[1]; boutsum += sir[2]; } } stackpointer = radius; for (x = 0; x < w; x++) { r[yi] = dv[rsum]; g[yi] = dv[gsum]; b[yi] = dv[bsum]; rsum -= routsum; gsum -= goutsum; bsum -= boutsum; stackstart = stackpointer - radius + div; sir = stack[stackstart % div]; routsum -= sir[0]; goutsum -= sir[1]; boutsum -= sir[2]; if (y == 0) { vmin[x] = Math.min(x + radius + 1, wm); } p = pix[yw + vmin[x]]; sir[0] = (p & 0xff0000) >> 16; sir[1] = (p & 0x00ff00) >> 8; sir[2] = (p & 0x0000ff); rinsum += sir[0]; ginsum += sir[1]; binsum += sir[2]; rsum += rinsum; gsum += ginsum; bsum += binsum; stackpointer = (stackpointer + 1) % div; sir = stack[(stackpointer) % div]; routsum += sir[0]; goutsum += sir[1]; boutsum += sir[2]; rinsum -= sir[0]; ginsum -= sir[1]; binsum -= sir[2]; yi++; } yw += w; } for (x = 0; x < w; x++) { rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0; yp = -radius * w; for (i = -radius; i <= radius; i++) { yi = Math.max(0, yp) + x; sir = stack[i + radius]; sir[0] = r[yi]; sir[1] = g[yi]; sir[2] = b[yi]; rbs = r1 - Math.abs(i); rsum += r[yi] * rbs; gsum += g[yi] * rbs; bsum += b[yi] * rbs; if (i > 0) { rinsum += sir[0]; ginsum += sir[1]; binsum += sir[2]; } else { routsum += sir[0]; goutsum += sir[1]; boutsum += sir[2]; } if (i < hm) { yp += w; } } yi = x; stackpointer = radius; for (y = 0; y < h; y++) { // Preserve alpha channel: ( 0xff000000 & pix[yi] ) pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16) | (dv[gsum] << 8) | dv[bsum]; rsum -= routsum; gsum -= goutsum; bsum -= boutsum; stackstart = stackpointer - radius + div; sir = stack[stackstart % div]; routsum -= sir[0]; goutsum -= sir[1]; boutsum -= sir[2]; if (x == 0) { vmin[y] = Math.min(y + r1, hm) * w; } p = x + vmin[y]; sir[0] = r[p]; sir[1] = g[p]; sir[2] = b[p]; rinsum += sir[0]; ginsum += sir[1]; binsum += sir[2]; rsum += rinsum; gsum += ginsum; bsum += binsum; stackpointer = (stackpointer + 1) % div; sir = stack[stackpointer]; routsum += sir[0]; goutsum += sir[1]; boutsum += sir[2]; rinsum -= sir[0]; ginsum -= sir[1]; binsum -= sir[2]; yi += w; } } bitmap.setPixels(pix, 0, w, 0, 0, w, h); return (bitmap); }}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209android4.3之后可使用,需要在build.gradle中配置:
defaultConfig { //BlurTransformation renderscriptTargetApi 23 renderscriptSupportModeEnabled true}123456通過animate()方法可以設置xml文件定義的4種補間動畫(alpha、scale、translate、rotate) 例如:
res/anim/left_in.xml
<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android"> <translate android:duration="@android:integer/config_mediumAnimTime" android:fromXDelta="-50%p" android:toXDelta="0"/> <alpha android:duration="@android:integer/config_mediumAnimTime" android:fromAlpha="0.0" android:toAlpha="1.0"/></set>123456789101112使用方式:
public class TestGlideActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test); ImageView targetView = (ImageView) findViewById(R.id.iv_target); Glide.with(this). load(R.drawable.test). asBitmap(). animate(R.anim.left_in).//加載xml文件定義的動畫 into(targetView); }}12345678910111213處理此外,還可以通過animate指定屬性動畫:
public class TestGlideActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test); ImageView targetView = (ImageView) findViewById(R.id.iv_target); ViewPropertyAnimation.Animator animationObject = new ViewPropertyAnimation.Animator() { @Override public void animate(View view) { //設置屬性動畫 ObjectAnimator moveIn = ObjectAnimator.ofFloat(view, "translationX", -500f, 0f); ObjectAnimator rotate = ObjectAnimator.ofFloat(view, "rotation", 0f, 360f); ObjectAnimator fadeInOut = ObjectAnimator.ofFloat(view, "alpha", 1f, 0f, 1f); ObjectAnimator moveTop = ObjectAnimator.ofFloat(view, "translationY", 0f, -2000, 0f); AnimatorSet animSet = new AnimatorSet(); //先左進,然后旋轉伴隨淡入效果,最后移動向上 animSet.play(rotate).with(fadeInOut).after(moveIn).before(moveTop); animSet.setDuration(5000); animSet.start(); } }; Glide.with(this). load(R.drawable.test). asBitmap(). animate(animationObject).//加載屬性動畫 into(targetView); }}1234567891011121314151617181920212223242526272829新聞熱點
疑難解答