android -- 重新认识ImageView的几种ScaleType

来源:互联网 发布:淘宝一淘怎么没有了 编辑:程序博客网 时间:2024/06/16 21:49

前言

最近项目里出现了个图片显示的小问题,就是类似朋友圈的这种,需求是图片只能有一张,并且这张图片来自屏幕截图(支持截长图),所以涉及到长图的展示,github 上有一些开源库,大致原理是利用 BitmapRegionDecoder 把长图切成n个小图展示,因为不想引用那么多第三方代码,项目需求也没说要加手势什么的并且只有一张图片,当然,还有懒,然后自己就想了个简单的方案:ScrollView 里嵌套 imageView。让 ImageView 宽和高自适应。因为测试的机型屏幕大小都差不多,所以当时并未发现什么问题,当上线后,有客户反映,有的图片显示不全(被放大裁剪了)。最后研究是图片展示格式的问题。

what–具体问题

因为发现是在某些小屏幕手机上有些图片显示不完整,在屏幕大的手机上就不会。
显然,如果图片本身宽高大于手机屏幕宽高,图片就被截取了,所以用户就看不到完整的图片,并且显示图片被放大了,所以可以首先猜想一下是图片显示格式的问题。

why–问题原因

要想明白问题是如何产生的,首先我们看看 ImageView 显示的几种 ScaleType。
官方文档对它是这样解释的:”Options for scaling the bounds of an image to the bounds of this view”
借用 encienqi 的翻译:控制图片如何 resized/moved 来匹对 ImageView 的 size。

ImageView.ScaleType 是个枚举类型,共有 8 种取值

ImageView.ScaleType 含义 CENTER 按图片的原来size居中显示,当图片长/宽超过View的长/宽,则截取图片的居中部分显示(不进行缩放) CENTER_CROP 按比例扩大图片的size居中显示,使得图片长(宽)等于或大于View的长(宽) CENTER_INSIDE 将图片的内容完整居中显示,通过按比例缩小或原来的size使得图片长/宽等于或小于View的长/宽 FIT_CENTER 使用Matrix.ScaleToFit中CENTER方式缩放图像 FIT_END 使用Matrix.ScaleToFit中END 方式缩放图像 FIT_START 使用Matrix.ScaleToFit中START方式缩放图像 FIT_XY 使用Matrix.ScaleToFit中FILL方式缩放图像 MATRIX 用矩阵来绘制,动态缩小放大图片来显示


其中的 Matrix.ScaleToFit 的作用:控制 src rect 应该如何对齐到 setRectToRect() 的 dst rect 。有以下几种取值:

Matrix.ScaleToFit 含义 CENTER 把图片按比例扩大/缩小到View的宽度,居中显示 END 把图片按比例扩大/缩小到View的宽度,显示在View的下部分位置 START 把图片按比例扩大/缩小到View的宽度,显示在View的上部分位置 FILL 把图片扩大/缩小到View的大小显示,不按图片比例


光看文字好像看不出什么区别来,下面放一波图,对比一下,效果立即就出来了:

图中代码里获取到屏幕尺寸及图片尺寸( dp 单位),下面三个 ImageView 的宽高分别为 50 dp ,wrap_content , 200 dp (也就是图片比 ImageView 小,自适应,大 这三种情况),为了效果显示,ImageView 背景为黑色。

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

其中是否对图片进行缩放、当图片大小大于 ImageView 时图片是否被裁剪(显示不完整)、如果有缩放是否按原图宽高比等情况可以看图大致总结一下:

ImageView.ScaleType 缩放 保持原图比例 裁剪 CENTER N Y Y CENTER_CROP Y Y Y CENTER_INSIDE Y Y N FIT_CENTER Y Y N FIT_END Y Y N FIT_START Y Y N FIT_XY Y N N MATRIX N Y Y

how–知道了原理,我们来解决问题

首先,之前一个突出问题是图片被裁剪了,但是需求不允许这样做,因为被裁剪的地方可能包含重要信息。
而我之前的做法,是把 ImageView 的 ScaleType 设置为 center_crop 的,对照上表,嗯,是会被裁剪的。
然后其中的 fit_start , fit_end 位置有点不太满足需求,而 fit_xy 不安原图比例。所以可以选择f it_center 或者 center_inside.

注意:因为我项目里 imageView 的宽高设的是自适应的,所以有这几种选择,如果是定值,那么还要自行分析。

最后,看似简单的问题,如果不理解原理,修改的时候东一榔头西一棒子,即使碰对了,后面再有问题,也不好及时定位。

demo地址:demo

阅读全文
1 0
原创粉丝点击