转载请注明出处,谢谢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()是一个裁剪技术,即缩放图像让它填充到 ImageView 界限内并且裁剪额外的部分。ImageView 会被完全填充,但图像可能不会完整显示。
fitCenter() 是一个裁剪技术,即缩放图像让图像都测量出来等于或小于 ImageView 的边界范围。该图像将会完全显示,但可能不会填满整个 ImageView。
看本篇博客开头的那三句代码,我们先看Glide源码的fitCenter方法:
com.bumptech.glide.DrawableRequestBuilder
public DrawableRequestBuilder fitCenter() {
return transform(glide.getDrawableFitCenter());
}
public DrawableRequestBuilder transform(Transformation... 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 transform(
Transformation... transformations) {
//这个变量之后要用到,请留意 ⭐2
isTransformationSet = true;
if (transformations.length == 1) {
transformation = transformations[0];
} else {
transformation = new MultiTransformation(transformations);
}
return this;
}
我们看到将fitCenter的对象glide.getDrawableFitCenter()加入到了transformation;同理,如果是centerCrop,那么会将glide.getDrawableCenterCrop()加入到transformtion,之后Glide会根据传入的transformtion以某个图片处理格式来从网络下载图片。
fitCenter源码先分析到这里,现在我们进入Glide的源码查看into方法都做了哪些操作,
com.bumptech.glide.GenericRequestBuilder
public Target 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