Android ImageView属性ScaleType的源码解析

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中有postprepost是指当前矩阵左乘参数矩阵,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);
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值