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

前言

最近项目里出现了个图片显示的小问题,就是类似朋友圈的这种,需求是图片只能有一张,并且这张图片来自屏幕截图(支持截长图),所以涉及到长图的展示,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缩放保持原图比例裁剪
CENTERNYY
CENTER_CROPYYY
CENTER_INSIDEYYN
FIT_CENTERYYN
FIT_ENDYYN
FIT_STARTYYN
FIT_XYYNN
MATRIXNYY

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

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

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

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

demo地址:demo

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值