在泰国举行的谷歌开发者论坛上,谷歌为我们介绍了一个名叫 Glide 的图片加载库,作者是bumptech。这个库被广泛的运用在google的开源项目中,包括2014年google I/O大会上发布的官方app。
- 使用简单
- 可配置度高,自适应程度高
- 支持常见图片格式 Jpg png gif webp
- 支持多种数据源 网络、本地、资源、Assets 等
- 高效缓存策略 支持Memory和Disk图片缓存 默认Bitmap格式采用RGB_565内存使用至少减少一半
- 生命周期集成 根据Activity/Fragment生命周期自动管理请求
- 高效处理Bitmap 使用Bitmap Pool使Bitmap复用,主动调用recycle回收需要回收的Bitmap,减小系统回收压力.
然后呢,这篇文章的重点不完全放在了Glide上,重要的是完成了一个demo——RecyclerView+CardView+Glide加载图片实现瀑布流,写过瀑布流的都知道,这中间有个bug,滑动的时候item位置会变动,这效果就很难受了。本文参考了一位前辈的方法,将其移植到我们的demo中来,算是基本解决了这个问题。
去github上查看最新添加依赖:https://github.com/bumptech/glide
repositories {mavenCentral() // jcenter() works as well because it pulls from Maven Central
}dependencies {compile 'com.github.bumptech.glide:glide:3.7.0'compile 'com.android.support:support-v4:19.1.0'
}
如果你需要各种变换效果,你可以继续添加:
compile 'jp.wasabeef:glide-transformations:2.0.1'
compile 'jp.co.cyberagent.android.gpuimage:gpuimage-library:1.3.0'
最简单的使用:
Glide.with(this).load("http://inthecheesefactory.com/uploads/source/nestedfragment/fragments.png").into(imageView);
with()的参数:
load()的使用:
Glide基本可以load任何可以拿到的媒体资源,load的参数也不局限于String类型。
可以拿到的资源:
load()的参数类型:
看一下Demo效果:
"加载资源图片");Glide.with(this).load(R.mipmap.ic_launcher).into(mIvGlide2);mTvGlide3.setText("加载手机SD卡图片");String path = Environment.getExternalStorageDirectory() + "/back.jpg";File file = new File(path);Uri uri = Uri.fromFile(file);Glide.with(this).load(uri).into(mIvGlide3);mTvGlide4.setText("加载网络gif");String gifUrl = "http://b.hiphotos.baidu.com/zhidao/pic/item/faedab64034f78f066abccc57b310a55b3191c67.jpg";Glide.with(this).load(gifUrl).into(mIvGlide4);mTvGlide5.setText("加载资源gif");Glide.with(this).load(R.drawable.loading).into(mIvGlide5);mTvGlide6.setText("加载本地gif");String path1 = Environment.getExternalStorageDirectory() + "/meinv2.jpg";File file1 = new File(path1);Uri uri1 = Uri.fromFile(file1);Glide.with(this).load(uri1).placeholder(R.mipmap.ic_launcher).into(mIvGlide6);mTvGlide7.setText("加载本地小视频和快照");String path2 = Environment.getExternalStorageDirectory() + "/video.mp4";File file2 = new File(path2);Uri uri2 = Uri.fromFile(file2);Glide.with(this).load(uri2).placeholder(R.mipmap.ic_launcher).into(mIvGlide7);mTvGlide8.setText("设置缩略图比例,然后,先加载缩略图,再加载原图");Glide.with(this).load("http://7xi8d6.com1.z0.glb.clouddn.com/2017-04-28-18094719_120129648541065_8356500748640452608_n.jpg").thumbnail(0.1f).centerCrop().placeholder(R.mipmap.ic_launcher).into(mIvGlide8);mTvGlide9.setText("先建立一个缩略图对象,然后,先加载缩略图,再加载原图");DrawableRequestBuilder builder = Glide.with(this).load("http://7xi8d6.com1.z0.glb.clouddn.com/2017-04-28-18094719_120129648541065_8356500748640452608_n.jpg");Glide.with(this).load(uri2).thumbnail(builder).centerCrop().placeholder(R.mipmap.ic_launcher).into(mIvGlide9);}
Glide的各种变换效果:
效果都在注释中,你可以看效果来进行选择哪种变换。有些我也叫不出是啥,尴尬….还是看demo效果吧。
@Override
public void onBindViewHolder(TransViewHolder holder, int position) {int integer = Integer.parseInt(mList.get(position));holder.mTvTran.setText("样式"+(position+1));switch (integer) {//五角星形的外框Maskcase 1: {int width = UIUtils.dip2px(mContext, 133.33f);int height = UIUtils.dip2px(mContext, 126.33f);Glide.with(mContext).load(R.drawable.demo).override(width, height).bitmapTransform(new CenterCrop(mContext),new MaskTransformation(mContext, R.drawable.mask_starfish)).into(holder.mIvTran);break;}//点9图片的外框Maskcase 2: {int width = UIUtils.dip2px(mContext, 150.0f);int height = UIUtils.dip2px(mContext, 100.0f);Glide.with(mContext).load(R.drawable.demo).override(width, height).bitmapTransform(new CenterCrop(mContext),new MaskTransformation(mContext, R.drawable.mask_chat_right)).into(holder.mIvTran);break;}//裁剪图片的上方部分区域case 3:Glide.with(mContext).load(R.drawable.demo).bitmapTransform(new CropTransformation(mContext, 300, 100, CropTransformation.CropType.TOP)).into(holder.mIvTran);break;//裁剪图片的上方100-300区域case 4:Glide.with(mContext).load(R.drawable.demo).bitmapTransform(new CropTransformation(mContext, 300, 100)).into(holder.mIvTran);break;//裁剪图片的下方部分区域case 5:Glide.with(mContext).load(R.drawable.demo).bitmapTransform(new CropTransformation(mContext, 300, 100, CropTransformation.CropType.BOTTOM)).into(holder.mIvTran);break;//显示方形图case 6:Glide.with(mContext).load(R.drawable.demo).bitmapTransform(new CropSquareTransformation(mContext)).into(holder.mIvTran);break;//显示圆形图case 7:Glide.with(mContext).load(R.drawable.demo).bitmapTransform(new CropCircleTransformation(mContext)).into(holder.mIvTran);break;//彩色滤镜样式case 8:Glide.with(mContext).load(R.drawable.demo).bitmapTransform(new ColorFilterTransformation(mContext, Color.argb(80, 255, 0, 0))).into(holder.mIvTran);break;//灰度图case 9:Glide.with(mContext).load(R.drawable.demo).bitmapTransform(new GrayscaleTransformation(mContext)).into(holder.mIvTran);break;//边框圆角化图片case 10:Glide.with(mContext).load(R.drawable.demo).bitmapTransform(new RoundedCornersTransformation(mContext, 30, 0,RoundedCornersTransformation.CornerType.BOTTOM)).into(holder.mIvTran);break;//毛玻璃效果case 11:Glide.with(mContext).load(R.drawable.check).bitmapTransform(new BlurTransformation(mContext, 25)).into(holder.mIvTran);break;case 12:Glide.with(mContext).load(R.drawable.demo).bitmapTransform(new ToonFilterTransformation(mContext)).into(holder.mIvTran);break;case 13:Glide.with(mContext).load(R.drawable.check).bitmapTransform(new SepiaFilterTransformation(mContext)).into(holder.mIvTran);break;case 14:Glide.with(mContext).load(R.drawable.check).bitmapTransform(new ContrastFilterTransformation(mContext, 2.0f)).into(holder.mIvTran);break;case 15:Glide.with(mContext).load(R.drawable.check).bitmapTransform(new InvertFilterTransformation(mContext)).into(holder.mIvTran);break;case 16:Glide.with(mContext).load(R.drawable.check).bitmapTransform(new PixelationFilterTransformation(mContext, 20)).into(holder.mIvTran);break;case 17:Glide.with(mContext).load(R.drawable.check).bitmapTransform(new SketchFilterTransformation(mContext)).into(holder.mIvTran);break;case 18:Glide.with(mContext).load(R.drawable.check).bitmapTransform(new SwirlFilterTransformation(mContext, 0.5f, 1.0f, new PointF(0.5f, 0.5f))).into(holder.mIvTran);break;case 19:Glide.with(mContext).load(R.drawable.check).bitmapTransform(new BrightnessFilterTransformation(mContext, 0.5f)).into(holder.mIvTran);break;case 20:Glide.with(mContext).load(R.drawable.check).bitmapTransform(new KuwaharaFilterTransformation(mContext, 25)).into(holder.mIvTran);break;case 21:Glide.with(mContext).load(R.drawable.check).bitmapTransform(new VignetteFilterTransformation(mContext, new PointF(0.5f, 0.5f),new float[] { 0.0f, 0.0f, 0.0f }, 0f, 0.75f)).into(holder.mIvTran);break;}
}
Glide的小综合案列(RecyclerView+CardView加载美女图片):
使用CardView:
app:cardBackgroundColor //这是设置背景颜色
app:cardCornerRadius //这是设置圆角大小
app:cardElevation //这是设置z轴的阴影
app:cardMaxElevation //这是设置z轴的最大高度值
app:cardUseCompatPadding //是否使用CompatPadding
app:cardPreventCornerOverlap //是否使用PreventCornerOverlap
app:contentPadding // 设置内容的padding
app:contentPaddingLeft //设置内容的左padding
app:contentPaddingTop //设置内容的上padding
app:contentPaddingRight //设置内容的右padding
app:contentPaddingBottom //设置内容的底padding
我的item_mm.xml如下,其中CardView的高度要设置为wrap_content,ImageView的高度也要设置为wrap_content。别问我为什么,我也不准备回答这个问题,因为我也不知道,你可以设置成别的试试就知道了。
<android.support.v7.widget.CardView
xmlns:android&#61;"http://schemas.android.com/apk/res/android"xmlns:app&#61;"http://schemas.android.com/apk/res-auto"app:cardCornerRadius&#61;"3dp"app:cardElevation&#61;"3dp"android:layout_width&#61;"wrap_content"android:layout_height&#61;"wrap_content"android:orientation&#61;"vertical"><ImageView
android:id&#61;"&#64;&#43;id/iv_mm"android:layout_width&#61;"wrap_content"android:layout_height&#61;"wrap_content"android:scaleType&#61;"centerCrop"/>android.support.v7.widget.CardView>
配置权限&#xff1a;
<uses-permission android:name&#61;"android.permission.INTERNET"/>
<uses-permission android:name&#61;"android.permission.WRITE_EXTERNAL_STORAGE" />
编写Addapter类&#xff0c;在onBindViewHolder中使用Glide通过URL加载图片即可&#xff1a;
public class MeiziAdapter extends RecyclerView.Adapter<MeiziAdapter.ViewHolder>{private Context mContext;private List
}
问题&#xff1a;现在我们已经可以实现加载图片的效果了&#xff0c;但是在上下滑动时&#xff0c;出现重新定义宽高&#xff0c;导致cardview滑动状态。这篇文章也提到这件事。我参考一个开源的软件中的写法&#xff0c;附在下面&#xff1a;
在Adapter中重写getItemViewType方法&#xff1b;
&#64;Override
public int getItemViewType(int position) {WindowManager windowManager &#61; (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);DisplayMetrics dm &#61; new DisplayMetrics();Display display &#61; windowManager.getDefaultDisplay();display.getMetrics(dm);final int screenWidth &#61; dm.widthPixels;return Math.round((float) screenWidth / (float) mData.get(position).getHeight() * 10f);
}
对我们的Meizi.java添加一个属性——高度height&#xff0c;并生成getter、setter方法&#xff1b;
......
private int height;public int getHeight() {return height;
}public void setHeight(int height) {this.height &#61; height;
}public boolean isError() {return error;
}
.......
下面着重是我们的onBindViewHolder方法&#xff0c;主体思想还是根据宽度获取该显示的高度。
&#64;Override
public void onBindViewHolder(final ViewHolder holder, final int position) {//存在记录的高度时先Layout再异步加载图片if (mData.get(holder.getAdapterPosition()).getHeight() > 0) {ViewGroup.LayoutParams layoutParams &#61; holder.mIvMm.getLayoutParams();layoutParams.height &#61; mData.get(holder.getAdapterPosition()).getHeight();}//获取屏幕宽度WindowManager windowManager &#61; (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);DisplayMetrics dm &#61; new DisplayMetrics();Display display &#61; windowManager.getDefaultDisplay();display.getMetrics(dm);final int screenWidth &#61; dm.widthPixels;String url &#61; mData.get(position).getResults().get(0).getUrl();Glide.with(mContext).load(url).asBitmap().diskCacheStrategy(DiskCacheStrategy.ALL).into(new SimpleTarget
}
源码链接