ImageView的ScaleType决定了图片在ImageView中的缩放形式。本文从ImageView的源码角度,结合图表展示不同ScaleType状态下图片的展示形式。下图所示为Android给ImageView定义的ScaleType枚举类,包含了八种ScaleType类型:
![img_83a7b15e328c28f4def7b75b8f803524.png](https://yqfile.alicdn.com/img_83a7b15e328c28f4def7b75b8f803524.png?x-oss-process=image/resize,w_1400/format,webp)
当用户在设置了ImageView的ScaleType后,ImageView会根据ScaleType的值进行图片的缩放,代码实现在ImageView.java类的private void configureBounds()函数中:
![img_e8d7ae62f51d35c13c14e09380406dad.png](https://yqfile.alicdn.com/img_e8d7ae62f51d35c13c14e09380406dad.png?x-oss-process=image/resize,w_1400/format,webp)
1、MATRIX
该模式下ImageView用户设置的比例缩放图片,经过MATRIX缩放后的图片将从ImageView的左上角开始绘制。如果缩放后的图片大于ImageView,那么多余的部分则剪裁掉,如果小于ImageView,则不作做任何处理。因此可能出现如下的图片展示形式,其中实线框表示ImageView,虚线表示图片。
![img_3e25dec6af5488b77c508d662dd9ba78.png](https://yqfile.alicdn.com/img_3e25dec6af5488b77c508d662dd9ba78.png?x-oss-process=image/resize,w_1400/format,webp)
该模式下图片从ImageView的左上角开始绘制,但不会超出ImageView,超出的部分不再显示。
2、CENTER
![img_e5835ff674de1a31e7a07d072b2ee1d7.png](https://yqfile.alicdn.com/img_e5835ff674de1a31e7a07d072b2ee1d7.png?x-oss-process=image/resize,w_1400/format,webp)
该模式按图片的原有的尺寸居中显示,当图片长/宽超过View的长/宽,则截取图片的居中部分显示,分为以下四种场景:
![img_5597655d13ece3d2b605705353bb4eae.png](https://yqfile.alicdn.com/img_5597655d13ece3d2b605705353bb4eae.png?x-oss-process=image/resize,w_1400/format,webp)
当dwidth>vwidth,dheight<vheight时,其实就是将图片左移和向下移动到ImageView的中央位置展示,展示图片的中间区域。
![img_da3d24c75e07b8ef40a1f6e6cd669ca2.png](https://yqfile.alicdn.com/img_da3d24c75e07b8ef40a1f6e6cd669ca2.png?x-oss-process=image/resize,w_1400/format,webp)
当dwidth<vwidth,dheight<vheight时,其实就是将图片向右和向上移动到ImageView的中央位置展示。
![img_4100ed7a9d495eba0b027c28e05c39af.png](https://yqfile.alicdn.com/img_4100ed7a9d495eba0b027c28e05c39af.png?x-oss-process=image/resize,w_1400/format,webp)
当dwidth>vwidth,dheight>vheight时,其实就是将图片向左和向上移动到ImageView的中央位置展示,展示图片中间内容。
![img_5b7fa9840417cadda43b8af63536b2b3.png](https://yqfile.alicdn.com/img_5b7fa9840417cadda43b8af63536b2b3.png?x-oss-process=image/resize,w_1400/format,webp)
当dheight>vheight,dwidth<vwidth,其实就是将图片向右和向上移动到ImageView的中央位置展示,展示图片中间内容。
3、CENTER_CROP
![img_9032d8f2a97b0094799dd7766e05eda2.png](https://yqfile.alicdn.com/img_9032d8f2a97b0094799dd7766e05eda2.png?x-oss-process=image/resize,w_1400/format,webp)
该模式按比例扩大图片的尺寸并居中显示,使得图片长(宽)等于或大于View的长(宽)。
如果dwidth/dheight>vwidth/vheight(图片的宽高比大于ImageView的宽高比),即vheight/dheight>vwidth/dwidth,也就是说ImageView和图片高度比小于ImageView和图片的宽度比,这时候取vheight/dheight的比例进行图片缩放,这样就能保证图片宽度在进行同等比例缩放的时候,图片宽度大于或等于ImageView的宽度,因为(vheight/dheight)* dwidth>vwidth。
同理,如果vwidth/dwidth>vheight/dheight时,取vwidth/dwidth作为图片的缩放比例,可以保证缩放完成后图片宽度等于ImageView的宽度,图片的高度大于或等于ImageView的高度,因为(vwidth/dwidth)*dheight>vheight。图片在缩放之后再进行CENTER操作即可。
![img_f68c5802b840624482bb2fb05744ad6d.png](https://yqfile.alicdn.com/img_f68c5802b840624482bb2fb05744ad6d.png?x-oss-process=image/resize,w_1400/format,webp)
上图所示,vwidth/dwidth>vheight/dheight,图片先按照vwidth/dwidth进行缩放,缩放后的图片高度>=vheight,然后再进行向上移位。
![img_ea98db75c4bb6e61d88bf4df49290098.png](https://yqfile.alicdn.com/img_ea98db75c4bb6e61d88bf4df49290098.png?x-oss-process=image/resize,w_1400/format,webp)
上图所示,vheight/dheight>vwidth/dwidth,图片先按照vheight/dheight进行缩放,缩放后的图片宽度>=vwidth,然后再进行想左移位。
4、CENTER_INSIDE
![img_d8afc22380320eebdb0ccbd5ed0de17a.png](https://yqfile.alicdn.com/img_d8afc22380320eebdb0ccbd5ed0de17a.png?x-oss-process=image/resize,w_1400/format,webp)
该模式将图片的内容完整居中显示,通过按比例缩小或原图片的尺寸,使得图片长或者宽等于或小于ImageView的长或者宽,这种方式允许图片不塞满整个ImageView。如果图片宽度dwidth小于ImageView的宽度vwidth,且图片高度dheight小于ImageView高度vheight,则图片的显示如下:
![img_0300c14b5435ecaff8b0a111885ead97.png](https://yqfile.alicdn.com/img_0300c14b5435ecaff8b0a111885ead97.png?x-oss-process=image/resize,w_1400/format,webp)
CENTER_INSIDE和CENTER_CROP选择缩放比例的策略正好相反,CENTER_INSIDE始终选择较小的比例进行缩放,保证缩放后的一个边(宽或高)小于ImageView的宽或高。下图所示为vheight/dheight>vwidth/dwidth的场景,取vwidth/dwidth作为图片的缩放比例,保证了缩放后图片高度小于或等于ImageView的高度(vwidth/dwidth)*dheight<=vheight。
![img_b8810e1574b259cff1dce31792ec5c81.png](https://yqfile.alicdn.com/img_b8810e1574b259cff1dce31792ec5c81.png?x-oss-process=image/resize,w_1400/format,webp)
下图所示为vwidth/dwidth>vheight/dheight的场景,取vheight/dheight作为图片的缩放比例,保证了缩放后图片宽度小于或等于ImageView的宽度,(vheight/dheight)*dwidth<=vwidth。
![img_dab6e1280e397990d7db1766bdab0b54.png](https://yqfile.alicdn.com/img_dab6e1280e397990d7db1766bdab0b54.png?x-oss-process=image/resize,w_1400/format,webp)
5、FIT_XY、FIT_CENTER、FIT_START、FIT_END
当ImageView设置了这四种ScaleType后,ImageView采用Matrit.ScaleToFit来进行图片的展示。
![img_45af0194e38714869359f93c8b611b49.png](https://yqfile.alicdn.com/img_45af0194e38714869359f93c8b611b49.png?x-oss-process=image/resize,w_1400/format,webp)
![img_58599a39bf77dcf2f6774f1b577d5294.png](https://yqfile.alicdn.com/img_58599a39bf77dcf2f6774f1b577d5294.png?x-oss-process=image/resize,w_1400/format,webp)
![img_87e0fa201a42187adaacd5cc5dab93e2.png](https://yqfile.alicdn.com/img_87e0fa201a42187adaacd5cc5dab93e2.png?x-oss-process=image/resize,w_1400/format,webp)
可以看出ScaleToFit有如下类型:
FILL:相当于ScaleType.FIT_XY,图片宽度和高度有独立的缩放比例,保证图片能够塞满整个ImageView。这种场景下图片宽度的缩放比例为vwidth/dwidth,高度的缩放比例为vheight/dheight。,
FIT_START,FIT_CENTER,FIT_END采用的缩放策略一样,如果dheight> dwidth,则使用vwidth/dwidth作为缩放比例,反之使用vheight/dheight作为缩放比例。
START:相当于ScaleType.FIT_START。把图片按比例扩大/缩小到View的宽度或高度,显示在View的left和top位置(图片会完整显示)。如下图所示:
![img_7a08e86562ba3668f8b677635491170e.png](https://yqfile.alicdn.com/img_7a08e86562ba3668f8b677635491170e.png?x-oss-process=image/resize,w_1400/format,webp)
CENTER:相当于ScaleType.FIT_CENTER,把图片按比例扩大/缩小到View的宽度或高度,居中显示(图片会完整显示)。如下图所示:
![img_fd9c4b75f97155b8611a1ab52df2407b.png](https://yqfile.alicdn.com/img_fd9c4b75f97155b8611a1ab52df2407b.png?x-oss-process=image/resize,w_1400/format,webp)
END:相当于ScaleType.FIT_END,把图片按比例扩大/缩小到View的宽度或高度,显示在View的right和bottom位置(图片会完整显示)。如下图所示:
![img_caa3693d0e654824ca2a32c1d9f1d383.png](https://yqfile.alicdn.com/img_caa3693d0e654824ca2a32c1d9f1d383.png?x-oss-process=image/resize,w_1400/format,webp)