ImageView的ScaleType的属性,一共有八个,一般都是自己看着来用,最近开发时,需要修改图片的缩放,理解了一波ScaleType的属性,总结一下。
属性值 | 作用 |
---|---|
MATRIX | 使用setImageMatrix(Matrix),允许用户自定义缩放、平移、透视来变形 |
FIT_XY | 缩小或放大图片,充满控件,不裁剪,可能会改变图片纵横比 |
FIT_START | 缩小或放大图片,未充满控件,保证纵横比,从原点开始,保证长宽有一个是完整的 |
FIT_CENTER | 缩小或放大图片,未充满控件,保证纵横比,保证长宽有一个是完整的,显示在中间 |
FIT_END | 缩小或放大图片,未充满控件,保证纵横比,从底部右边开始,保证长宽有一个是完整 |
CENTER | 不缩放,充满控件,会裁剪,保证纵横比,显示在中央 |
CENTER_CROP | 缩放图片,保证纵横比,使长宽等于或大于视图的尺寸,显示在中央,会剪裁 也就是说保证图片的短边能显示出来,而长边不会完整的显示 |
CENTER_INSIDE | 缩放图片,保证纵横比,,使长宽等于或小于视图的尺寸,显示在中央 |
-
MATRIX
MATRIX
是一个矩阵类,是用来对图片进行缩放、平移、旋转等操作,主要有:-
translate 平移
mMaritx.setTranslate(float dx,float dy)
-
Rotate 旋转
mMaritx.setRotate(float degrees, float px, float py)//旋转角度,旋转中心
-
scale 缩放
mMartix.setScale(float sx, float sy,float px,float py) //
-
skew 倾斜
mMartix.setSkew(float sx, float sy,float px,float py) //
-
矩阵的乘法是只有左乘的概念,需要(m*n)*(n*m)
,但是由于mMartix是一个3*3的矩阵,因此可以左乘和右乘,这种概念毫无用处,只是因为它提供的Api中有post
和pre
,post
是指当前矩阵左乘参数矩阵,pre
是指参数矩阵乘以当前矩阵,因此如果你的变化是连续的,需要分清先后顺序。
//源码解析
if (ScaleType.MATRIX == mScaleType) {
// Use the specified matrix as-is.
if (mMatrix.isIdentity()) {
mDrawMatrix = null;
} else {
mDrawMatrix = mMatrix;
}
由此可以见到,其是将参数矩阵mMatrix
给了mDrawMatrix
,然后在Draw()
时调用mDrawMatrix
.
使用时,需要先将矩阵填入,再使用类型
setScaleType(ScaleType.MATRIX);
setImageMatrix(mMatrix);
setScaleType时会重新刷新。
-
FIT_XY
-
FIT_START
-
FIT_CENTER
-
FIT_END
以上方法时,使用了JNI,没有查到源码
-
CENTER
//vwidth 控件宽 vheight 控件高 //dwidth 图片宽 //dheight 图片高 if (ScaleType.CENTER == mScaleType) { // Center bitmap in view, no scaling. mDrawMatrix = mMatrix; mDrawMatrix.setTranslate(Math.round((vwidth - dwidth) * 0.5f), Math.round((vheight - dheight) * 0.5f));
由源码可知,只是将其进行了平移,移动到控件的中间。
-
CENTER_CROP
这个我理解了很久,使用代数法进行了一波实验,保证有一边是可以完全展示出来的,另一边是超过控件大小的,最后再平移到控件中间,但是它对于裁边的处理,是通过图片宽高比和控件的宽高比进行比较,得到应该哪边完全展示出来。
//vwidth 控件宽 vheight 控件高 //dwidth 图片宽 //dheight 图片高 if (ScaleType.CENTER_CROP == mScaleType) { mDrawMatrix = mMatrix; float scale; float dx = 0, dy = 0; if (dwidth * vheight > vwidth * dheight) { scale = (float) vheight / (float) dheight; dx = (vwidth - dwidth * scale) * 0.5f; } else { scale = (float) vwidth / (float) dwidth; dy = (vheight - dheight * scale) * 0.5f; } mDrawMatrix.setScale(scale, scale); mDrawMatrix.postTranslate(Math.round(dx), Math.round(dy));
可以这么理解,图片宽高比>控件宽高比,图片高度是可以保证通过缩放完全显示,宽边会超过控件宽度,反之则是图片宽度是可以保证通过缩放完全显示,高度会超过控件高度。
-
CENTER_INSIDE
- 当图片宽高都小于控件的宽高时,则不会缩放
- 当图片宽高有一边大于控件的宽高时,则会选择长边的缩放比例,保证长边充满控件,而短边完全显示却不充满控件
- 最后平移到中间
if (ScaleType.CENTER_INSIDE == mScaleType) { mDrawMatrix = mMatrix; float scale; float dx; float dy; if (dwidth <= vwidth && dheight <= vheight) { scale = 1.0f; } else { scale = Math.min((float) vwidth / (float) dwidth, (float) vheight / (float) dheight); } dx = Math.round((vwidth - dwidth * scale) * 0.5f); dy = Math.round((vheight - dheight * scale) * 0.5f); mDrawMatrix.setScale(scale, scale); mDrawMatrix.postTranslate(dx, dy);