Glide centerCrop fitCenter和ImageView的scaleType的关系,互相影响的探讨
来源:互联网 发布:图解组合模式 java 编辑:程序博客网 时间:2024/05/17 21:06
转载请注明出处,谢谢http://blog.csdn.net/harryweasley/article/details/71526216
在使用Glide的过程中,你一定见过下面的代码方式:
ImageView imageView = (ImageView) findViewById(R.id.image); imageView.setScaleType(ImageView.ScaleType.FIT_START); Glide.with(this).load("https://zhitu.isux.us/assets/img/imgSample/test-60.jpg").fitCenter().into(imageView);
ImageView有自己的scaleType,Glide又有自己的fitCenter或者centerCrop,那这两者的关系到底是怎么样的,是否会互相影响呢,本篇博客就来探讨这个问题的。
Glide提供了两个标准选项来处理图像的显示问题,一个是centerCrop一个是fitCenter:
CenterCrop
CenterCrop()是一个裁剪技术,即缩放图像让它填充到 ImageView 界限内并且裁剪额外的部分。ImageView 会被完全填充,但图像可能不会完整显示。
FitCenter
fitCenter() 是一个裁剪技术,即缩放图像让图像都测量出来等于或小于 ImageView 的边界范围。该图像将会完全显示,但可能不会填满整个 ImageView。
看本篇博客开头的那三句代码,我们先看Glide源码的fitCenter方法:
com.bumptech.glide.DrawableRequestBuilder
public DrawableRequestBuilder<ModelType> fitCenter() { return transform(glide.getDrawableFitCenter()); }public DrawableRequestBuilder<ModelType> transform(Transformation<GifBitmapWrapper>... transformation) { super.transform(transformation); return this; }
DrawableRequestBuilder的transform调用父类的transform,继续看父类的源码:
com.bumptech.glide.GenericRequestBuilder
/** * Transform resources with the given {@link Transformation}s. Replaces any existing transformation or * transformations. * 用给定的Transformation转换资源。替换任何已存在的transformation或者transformations。⭐1 * @param transformations the transformations to apply in order. * @return This request builder. */ public GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeType> transform( Transformation<ResourceType>... transformations) { //这个变量之后要用到,请留意 ⭐2 isTransformationSet = true; if (transformations.length == 1) { transformation = transformations[0]; } else { transformation = new MultiTransformation<ResourceType>(transformations); } return this; }
我们看到将fitCenter的对象glide.getDrawableFitCenter()加入到了transformation;同理,如果是centerCrop,那么会将glide.getDrawableCenterCrop()加入到transformtion,之后Glide会根据传入的transformtion以某个图片处理格式来从网络下载图片。
fitCenter源码先分析到这里,现在我们进入Glide的源码查看into方法都做了哪些操作,
com.bumptech.glide.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)); }
首先看这个判断 if (!isTransformationSet && view.getScaleType() != null)
由ImageView的源码可知,每一个ImageView都有个默认的fitCenter的scaleType,ImageView的源码:
public ImageView(Context context) { super(context); initImageView(); } public ImageView(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public ImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { this(context, attrs, defStyleAttr, 0); } public ImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); initImageView(); ... } private void initImageView() { ... //将FIT_CENTER设置为默认的scaleType mScaleType = ScaleType.FIT_CENTER; ... }
我们可以看到,每个ImageView都会默认将 mScaleType = ScaleType.FIT_CENTER
由以上得知unview.getScaleType() != null一定为true,
这里的isTransformationSet 是不是很熟悉,没错,就是上面⭐2说的要用到的那个变量,
从这里可以看出如果Glide如果执行了centerCrop或者fitCenter,那么 if (!isTransformationSet && view.getScaleType() != null)里面的代码将不会执行。
那么如果Glide没有执行centerCrop和fitCenter,if (!isTransformationSet && view.getScaleType() != null)里面的代码将会执行,我们会看到,他根据传入的ImageView的scaleType做了两件事情,执行applyCenterCrop()或者applyFitCenter(),我们去源码中看看:
com.bumptech.glide.GenericRequestBuilder
void applyCenterCrop() { // To be implemented by subclasses when possible. } void applyFitCenter() { // To be implemented by subclasses when possible. }
我们看到是一个空方法,具体实现是在子类中实现的,那我们就去子类DrawableRequestBuilder中看看,源码如下:
com.bumptech.glide.DrawableRequestBuilder
@Override void applyFitCenter() { fitCenter(); } @Override void applyCenterCrop() { centerCrop(); }
看到这里有没有恍然大悟,从这里我们可以到一个结论,如果我们没有给Glide手动添加centerCrop和fitCenter方法,Glide会根据传入的ImageView的scaleType来自己去执行centerCrop或者fitCenter方法。(我知道你一定会说,scaleType不仅仅是CENTER_CROP,FIT_CENTER,FIT_START,FIT_END,这个我知道的哈,后面还会继续说的。)
你以为这就是ImageView的scaleType在Glide里的作用吗,错了,这个scaleType在最后将图片设置到ImageView还起了一次作用。
在Glide获取到图片资源,会执行ImageView的setImageDrawable将图片设置进去,源码如下:
com.bumptech.glide.request.target.GlideDrawableImageViewTarget
/** * Sets the drawable on the view using * {@link android.widget.ImageView#setImageDrawable(android.graphics.drawable.Drawable)}. * * @param resource The {@link android.graphics.drawable.Drawable} to display in the view. */ @Override protected void setResource(GlideDrawable resource) { view.setImageDrawable(resource); }
综上可以总结一个结论:ImageView的scaleType在Glide加载图片到ImageView的过程中至少起一次作用。
经过我的多次测试,得出一个结论,如果ImageView的scaleType不是centerCrop,并且Glide没有调用centerCrop方法,那么Glide从服务器获取的图片格式是fitCenter格式,最终设置到ImageView图片的格式,还要根据ImageView的scaleType才能确定。
不知道,你是否注意到⭐1的标志,那边的一个注释说明了一个问题,如果Glide同时执行了centerCrop和fitCenter方法,那么谁在后面,就以谁的格式下载图片。
打个比方,代码如下:
Glide.with(this).load("https://zhitu.isux.us/assets/img/imgSample/test-60.jpg").fitCenter().centerCrop().into(imageView);
那么从网络下载到的图片是以centerCrop格式下载到的。
本篇博客最后,分析一下ImageView的8个scaleType:
CENTER 将图像置于视图中,但不执行缩放。 CENTER_CROP 缩放图像(保持图像的纵横比),使图像的尺寸(宽度和高度)都等于或大于视图的相应尺寸(减去填充)。所以会占满ImageView,但是可能会显示不完全图片 CENTER_INSIDE 缩小图像均匀(保持图像的纵横比),使图像的尺寸(宽度和高度)都等于或小于视图的对应尺寸(减去填充)。 FIT_CENTER 保持原图的纵横比计算一个比例,但是也要确保原图完全放入目标视图内, 至少一个轴(X或Y)将精确配合。 结果以目标视图为中心。默认属性 FIT_END 保持原图的纵横比计算一个比例,但是也要确保原图完全放入目标视图内, 至少一个轴(X或Y)将精确配合。END将结果对齐到目标视图右下边缘。 FIT_START 保持原图的纵横比计算一个比例,但是也要确保原图完全放入目标视图内, 至少一个轴(X或Y)将精确配合。 START将结果对齐到目标视图左上边缘。 FIT_XY 独立地缩放X和Y,使原图与目标完全匹配。 这可能会改变原图的宽高比。 MATRIX 绘制时使用图像矩阵进行缩放。最后再次总结一下本篇博客:
Glide从网络下载到的图片,会按照两种格式来下载,一种是centerCrop,一种是fitCenter,一旦下载下来后,设置到ImageView的时候,还会根据ImageView的scaleType来确立图片位置。
如果Glide没有手动调用过centerCrop和fitCenter,那么Glide从网络下载的图片格式,由ImageView的scaleType决定,如果scaleType是center_crop,那么Glide以centerCrop下载图片,如果scaleType是 FIT_CENTER,FIT_START,FIT_END,那么Glide以fitCenter格式下载图片。不过根据我这边的测试结果发现,如果scaleType是CENTER,CENTER_INSIDE,MATRIX,Glide也是以fitCenter格式下载图片的。
参考文章:
https://developer.android.com/reference/android/widget/ImageView.ScaleType.html
https://futurestud.io/tutorials/glide-image-resizing-scaling
http://www.jianshu.com/p/96fc561eada1
- Glide centerCrop fitCenter和ImageView的scaleType的关系,互相影响的探讨
- scaletype之centerInside,center,centerCrop,fitCenter之间的区别
- scaletype之centerInside,center,centerCrop,fitCenter之间的区别
- scaletype之centerInside,center,centerCrop,fitCenter之间的区别
- 【android】解决设置ImageView的scaletype为centerCrop后padding不起作用的办法
- 【android】解决设置ImageView的scaletype为centerCrop后padding不起作用的办法
- Glide设置圆角图片后设置ImageVIew的scanType="centerCrop"无效解决办法
- ImageView的scaletype
- ImageView的scaletype属性
- ImageView的scaletype属性
- ImageView的scaletype属性
- ImageView的Scaletype图解
- ImageView的scaletype属性
- ImageView的scaletype属性
- ImageView的ScaleType
- ImageView 的 scaleType 小结
- ImageView的Scaletype
- ImageView的Scaletype
- [李景山php] 依赖注入和设计模式
- 使用kxmenu时在UIBarButtonItem上frame无效
- oracle dump
- 各种应用服务指纹探测
- iOS10 提交AppStore不出现构建的版本
- Glide centerCrop fitCenter和ImageView的scaleType的关系,互相影响的探讨
- 第六届蓝桥杯总决赛 四阶幻方
- 添加MySQL到VS的C#项目中
- 各种宽度、高度
- Http状态码大全
- ReactNative之helloWorld
- java多线程(一)
- 大话设计模式,让你的代码更完美5---浅复制和深复制
- 今日头条的发家与困局