结合Glide实现很炫的图片效果框架(裁剪、圆形、正方形、圆角等)
git地址 : https://github.com/wasabeef/glide-transformations
使用步骤
- 在project的build.gradle添加如下代码(如下图)
allprojects {
repositories {
...
maven { url "https://jitpack.io" }
}
}
- 在Module的build.gradle添加依赖
compile ‘com.github.open-android:Glide-transformations:0.1.0’
- 用法(有很多种Translation)
//指定加载静态图
String url = "http://imgsrc.baidu.com/imgad/pic/item/267f9e2f07082838b5168c32b299a9014c08f1f9.jpg";
Glide.with(this).load(url)
.bitmapTransform(new BlurTransformation(this, 25), new CropCircleTransformation(this)).into(mIv1);
Glide的使用
1. 在moudle的build文件中添加
compile ‘com.github.bumptech.glide:glide:3.7.0’
加载本地图片
File file = new File(getExternalCacheDir() + "/image.jpg");
Glide.with(this).load(file).into(imageView);
// 加载应用资源
int resource = R.drawable.image;
Glide.with(this).load(resource).into(imageView);
// 加载二进制流
byte[] image = getImageBytes();
Glide.with(this).load(image).into(imageView);
// 加载Uri对象
Uri imageUri = getImageUri();
Glide.with(this).load(imageUri).into(imageView);`
- 如果指定是静态图片 asBitmap()
Glide.with(this).load(url)
.asBitmap()
.placeholder(R.mipmap.ic_launcher)
.error(R.drawable.rll_arrow)
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
.into(mIv1);
- 指定是gif图片
String gifUrl = "http://p1.pstatp.com/large/166200019850062839d3";
Glide.with(this).load(gifUrl).asGif().diskCacheStrategy(DiskCacheStrategy.SOURCE).override(100, 100).into(mIv2);
注意点:
a. gif可以用asBitmap()来强制加载静态图片,显示第一帧
b. 加载gif图一定要把diskCacheStrategy设置成NONE,或者是SOURCE,不配不行,因为不配默认就是ALL,这种情况下会把GIF图的每一帧都去压缩然后缓存,时间极长,可能要几分钟gif图才会显示出来。用glide加载gif图片的时候,一定要用diskCacheStrategy(DiskCacheStrategy.NONE)或者diskCacheStrategy(DiskCacheStrategy.SOURCE),要不然更容易OOM
c. 如果从网络加载的url 不确定是gif还是静态图片,那设置了diskCacheStrategy(DiskCacheStrategy.NONE) 虽然gif加载能变快,但是如果url是静态图片的话就少了硬盘缓存这一级了,用diskCacheStrategy(DiskCacheStrategy.SOURCE) 就行了
d. 占位图不支持使用gif的,如果一定要用gif的占位图,先用into()方法显示一张gif图,然后再调用一次into()方法,并传入SimpleTarget,等真正的图片加载出来,把显示的图片替换掉就行了。
- into()方法不仅可以添加ImageView,还可以添加其他参数
a. SimpleTarget
/**
* 获取gif的每一帧
*/
SimpleTarget<GlideDrawable> mGlideDrawableSimpleTarget = new SimpleTarget<GlideDrawable>() {
@Override
public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> glideAnimation) {
GifDrawable gifDrawable = (GifDrawable) resource;
GifDecoder decoder = gifDrawable.getDecoder();
for (int i = 0; i < decoder.getFrameCount(); i++) {
decoder.advance();
if(i == (decoder.getFrameCount() - 1)){
Bitmap bitmap = decoder.getNextFrame();
mIv1.setImageBitmap(bitmap);
break;
}
}
}
};
String gifUrl = "http://p1.pstatp.com/large/166200019850062839d3";
Glide.with(this).load(gifUrl).into(mGlideDrawableSimpleTarget);
b. ViewTarget
ViewTarget<ViewGroup, GlideDrawable> mViewTarget = new ViewTarget<ViewGroup, GlideDrawable>(mRootView) {
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
@Override
public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> glideAnimation) {
mRootView.setBackground(resource);
}
};
String bgUrl = "http://cn.bing.com/az/hprichbg/rb/TOAD_ZH-CN7336795473_1920x1080.jpg";
Glide.with(this).load(bgUrl).into(mViewTarget);
Glide的缓存
1. 在缓存这一功能上,Glide分成了两个模块,一个是内存缓存,一个是硬盘缓存。
a . 调用skipMemoryCache()方法并传入true,就表示禁用掉Glide的内存缓存功能
Glide.with(this)
.load(url)
.skipMemoryCache(true)
.into(imageView);
b. 调用diskCacheStrategy()方法并传入DiskCacheStrategy.NONE,就可以禁用掉Glide的硬盘缓存功能了
Glide.with(this)
.load(url)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(imageView);
diskCacheStrategy()方法基本上就是Glide硬盘缓存功能的一切,它可以接收四种参数:
DiskCacheStrategy.NONE: 表示不缓存任何内容。(加载gif图片时可选)
DiskCacheStrategy.SOURCE: 表示只缓存原始图片。(加载gif图片时不可选)
DiskCacheStrategy.RESULT: 表示只缓存转换过后的图片(默认选项)。(加载gif图片时可选)
DiskCacheStrategy.ALL : 表示既缓存原始图片,也缓存转换过后的图片。(加载gif图片时不可选)
- 清理缓存
Glide自带清除缓存的功能,分别对应Glide.get(context).clearDiskCache();(清除磁盘缓存)与Glide.get(context).clearMemory();(清除内存缓存)两个方法.其中clearDiskCache()方法必须运行在子线程,clearMemory()方法必须运行在主线程
封装的清理缓存的类:
public class GlideCacheUtils {
/*InternalCacheDiskCacheFactory.DEFAULT_DISK_CACHE_DIR与ExternalCacheDiskCacheFactory.DEFAULT_DISK_CACHE_DIR
获取到位于内部与外部存储的缓存文件夹的文件夹名,并通过context.getCacheDir()与
context.getExternalCacheDir()获取内部与外部存储的路径.*/
private static GlideCacheUtils inst;
public static GlideCacheUtils getInstance() {
if (inst == null) {
inst = new GlideCacheUtils();
}
return inst;
}
/**
* 清除图片磁盘缓存
*/
public void clearImageDiskCache(final Context context) {
try {
if (Looper.myLooper() == Looper.getMainLooper()) {
new Thread(new Runnable() {
@Override
public void run() {
Glide.get(context).clearDiskCache();
// BusUtil.getBus().post(new GlideCacheClearSuccessEvent());
}
}).start();
} else {
Glide.get(context).clearDiskCache();
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 清除图片内存缓存
*/
public void clearImageMemoryCache(Context context) {
try {
if (Looper.myLooper() == Looper.getMainLooper()) { //只能在主线程执行
Glide.get(context).clearMemory();
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 清除图片所有缓存
*/
public void clearImageAllCache(Context context) {
clearImageDiskCache(context);
clearImageMemoryCache(context);
String ImageExternalCatchDir=context.getExternalCacheDir()+ ExternalCacheDiskCacheFactory.DEFAULT_DISK_CACHE_DIR;
deleteFolderFile(ImageExternalCatchDir, true);
}
/**
* 获取Glide造成的缓存大小
*
* @return CacheSize
*/
public String getCacheSize(Context context) {
try {
return getFormatSize(getFolderSize(new File(context.getCacheDir() + "/"+ InternalCacheDiskCacheFactory.DEFAULT_DISK_CACHE_DIR)));
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
/**
* 获取指定文件夹内所有文件大小的和
*
* @param file file
* @return size
* @throws Exception
*/
private long getFolderSize(File file) throws Exception {
long size = 0;
try {
File[] fileList = file.listFiles();
for (File aFileList : fileList) {
if (aFileList.isDirectory()) {
size = size + getFolderSize(aFileList);
} else {
size = size + aFileList.length();
}
}
} catch (Exception e) {
e.printStackTrace();
}
return size;
}
/**
* 删除指定目录下的文件,这里用于缓存的删除
*
* @param filePath filePath
* @param deleteThisPath deleteThisPath
*/
private void deleteFolderFile(String filePath, boolean deleteThisPath) {
if (!TextUtils.isEmpty(filePath)) {
try {
File file = new File(filePath);
if (file.isDirectory()) {
File files[] = file.listFiles();
for (File file1 : files) {
deleteFolderFile(file1.getAbsolutePath(), true);
}
}
if (deleteThisPath) {
if (!file.isDirectory()) {
file.delete();
} else {
if (file.listFiles().length == 0) {
file.delete();
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 格式化单位
*
* @param size size
* @return size
*/
private static String getFormatSize(double size) {
double kiloByte = size / 1024;
if (kiloByte < 1) {
return size + "Byte";
}
double megaByte = kiloByte / 1024;
if (megaByte < 1) {
BigDecimal result1 = new BigDecimal(Double.toString(kiloByte));
return result1.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "KB";
}
double gigaByte = megaByte / 1024;
if (gigaByte < 1) {
BigDecimal result2 = new BigDecimal(Double.toString(megaByte));
return result2.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "MB";
}
double teraBytes = gigaByte / 1024;
if (teraBytes < 1) {
BigDecimal result3 = new BigDecimal(Double.toString(gigaByte));
return result3.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "GB";
}
BigDecimal result4 = new BigDecimal(teraBytes);
return result4.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "TB";
}
}
Glide有暂停、恢复 加载图片的功能
(RecyclerView在滑动时添加)
/**
* 滚动加载,不滚动时不加载,提高RecyclerView效率
*/
private void initEvent() {
mRv.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int scrollState) {
super.onScrollStateChanged(recyclerView, scrollState);
switch (scrollState){
case SCROLL_STATE_FLING:
Log.i("RecyclerView","用户在手指离开屏幕之前,由于滑了一下,视图仍然依靠惯性继续滑动");
Glide.with(MyApplication.getInstance()).pauseRequests();
//刷新
break;
case SCROLL_STATE_IDLE:
Log.i("RecyclerView", "视图已经停止滑动");
Glide.with(MyApplication.getInstance()).resumeRequests();
break;
case SCROLL_STATE_TOUCH_SCROLL:
Log.i("RecyclerView","手指没有离开屏幕,视图正在滑动");
Glide.with(MyApplication.getInstance()).resumeRequests();
break;
}
}
});
}
Glide加载时使用缩略图
thumbnail()方法的目的就是让用户先看到一个低解析度的图,点开后,再加载一个高解析度的图
加载本地图片时:
Glide.
with( context )
.load(R.mipmap.ic_launcher)
.thumbnail( 0.1f )//表示为原图的十分之一
.into( imageView2 );
加载网络图片时:
String url = "http://imgsrc.baidu.com/imgad/pic/item/267f9e2f07082838b5168c32b299a9014c08f1f9.jpg";
DrawableRequestBuilder<String> thumbnailRequest = Glide.with( this ).load(url );
Glide.with( this ).load( url ).thumbnail( thumbnailRequest ).into( mIv1 );
获取Glide的缓存图片
downloadOnly()方法是定义在DrawableTypeRequest类当中的,它有两个方法重载,一个接收图片的宽度和高度,另一个接收一个泛型对象,如下所示:
downloadOnly(int width, int height)
downloadOnly(Y target)
这两个方法各自有各自的应用场景,其中downloadOnly(int width, int height)是用于在子线程中下载图片的,而downloadOnly(Y target)是用于在主线程中下载图片的。
- downloadOnly(int width,int height) 在子线程中调用,然后通过FutureTarger的get()方法得到缓存图片的信息
public void downloadImage(View view) {
new Thread(new Runnable() {
@Override
public void run() {
try {
String url = "http://cn.bing.com/az/hprichbg/rb/TOAD_ZH-CN7336795473_1920x1080.jpg";
final Context context = getApplicationContext();
FutureTarget<File> target = Glide.with(context)
.load(url)
.downloadOnly(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL);
final File imageFile = target.get();
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(context, imageFile.getPath(), Toast.LENGTH_LONG).show();
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
之后我们可以使用如下代码去加载这张图片,图片就会立即显示出来,而不用再去网络上请求了
public void loadImage(View view) {
String url = "http://cn.bing.com/az/hprichbg/rb/TOAD_ZH-CN7336795473_1920x1080.jpg";
Glide.with(this)
.load(url)
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
.into(imageView);
}
需要注意的是,这里必须将硬盘缓存策略指定成DiskCacheStrategy.SOURCE或者DiskCacheStrategy.ALL,否则Glide将无法使用我们刚才下载好的图片缓存文件。
- 在主线程中调用downloadOnly(Targer xx)
使用DownloadImageTarget,注意Target接口的泛型必须指定成File对象,这是downloadOnly(Y target)方法要求的,代码如下所示:
public class DownloadImageTarget implements Target<File> {
private static final String TAG = "DownloadImageTarget";
@Override
public void onStart() {
}
@Override
public void onStop() {
}
@Override
public void onDestroy() {
}
@Override
public void onLoadStarted(Drawable placeholder) {
}
@Override
public void onLoadFailed(Exception e, Drawable errorDrawable) {
}
@Override
public void onResourceReady(File resource, GlideAnimation<? super File> glideAnimation) {
Log.d(TAG, resource.getPath());
}
@Override
public void onLoadCleared(Drawable placeholder) {
}
@Override
public void getSize(SizeReadyCallback cb) {
cb.onSizeReady(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL);
}
@Override
public void setRequest(Request request) {
}
@Override
public Request getRequest() {
return null;
}
}
由于是要直接实现Target接口,因此需要重写的方法非常多。这些方法大多是数Glide加载图片生命周期的一些回调,我们可以不用管它们,其中只有两个方法是必须实现的,一个是getSize()方法,一个是onResourceReady()方法。
Glide在开始加载图片之前会先计算图片的大小,然后回调到onSizeReady()方法当中,之后才会开始执行图片加载。而这里,计算图片大小的任务就交给我们了。只不过这是一个最简单的Target实现,在getSize()方法中就直接回调了Target.SIZE_ORIGINAL,表示图片的原始尺寸。
然后图片下载完成之后就会回调到onResourceReady()方法,在这个方法中只是打印了一下下载的图片文件的路径。
这样一个最简单的DownloadImageTarget就定义好了,使用它也非常的简单,我们不用再考虑什么线程的问题了,而是直接把它的实例传入downloadOnly(Y target)方法中即可,如下所示:
public void downloadImage(View view) {
String url = "http://cn.bing.com/az/hprichbg/rb/TOAD_ZH-CN7336795473_1920x1080.jpg";
Glide.with(this)
.load(url)
.downloadOnly(new DownloadImageTarget());
}
转载出自:
(http://blog.csdn.net/guolin_blog/article/details/70215985)
(http://blog.csdn.net/guolin_blog/article/details/54895665)
(http://blog.csdn.net/guolin_blog/article/details/53939176)
(http://blog.csdn.net/guolin_blog/article/details/53759439)