本文来自于腾讯bugly开发者社区,未经做者赞成,请勿转载,原文地址:http://dev.qq.com/topic/5832602d7196970d65901d76java
本文主要介绍了ImageView的相关重要方法,从源码角度剖析了一些容易使人混淆或百思不得其解的问题。android
src :为ImageView 原图内容,存放原图大小,不会被拉伸;微信
background:为Imageview的背景,会根据ImageView给定的长宽进行拉伸;app
在ImageView中,能够同时设置src和background属性(为了减小绘制,能够根据使用场景来设置相应属性); 因为src中存放的是原图大小,若是须要对其缩放,就须要使用android:scaleTyle这个属性(scaleType 只对src属性有效),另外还能够对background设置透明度。框架
设置ImageView的透明度有啥正确不正确的,如直接就mImageView.setAlpha(100),不就好了吗?(答案是不肯定,后续分析)异步
ImageView 设置透明度主要有如下三种方法:函数
setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) (View提供)工具
setAlpha(int alpha) (已经标记为@Deprecated)this
setImageAlpha(int alpha) (API>=16)spa
其中,setImageAlpha内部调用setAlpha(int alpha)方法,查看API可知,setAlpha 主要是针对image而言,使用setImageView,一方面在命名上更为贴切与View中的setAlpha方法区分,同时作好兼容性,目前只能使用在API>=16的场景。
另外, 像Drawable 和Paint中的都是调用setAlpha(int alpha)
在本节前就提了一个问题:直接使用mImageView.setAlpha(100),来设置ImageView的透明度是否正确?
正确答案是:
- android:src在设置ImageView的setAlpha(int alpha)时,起做用;
- android:background在设置ImageView的setAlpha(int alpha)时,不起做用。
为何呢?
在前面介绍中,已经指出ImageView中的setAlpha(int alpha)方法是针对image有效的,想弄清就直接看源码:
图1 ImageView 的setAlpha()
图2 ImageView的applyColorMod()
那么mDrawable 是怎样获得的了:
图3 ImageView构造函数 获取src设置的图片
setImageDrawable(Drawable d) 中调用 updateDrawable(Drawable d),而mDrawable 正是在updateDrawable(Drawable d)中赋值的:
图4 ImageView的updateDrawable()方法
如今知道为何有时候ImageView.setAlpha(int alpha)没起做用了吧。
直接引用Drawable.mutate()的JavaDoc:
Make this drawable mutable. This operation cannot be reversed. A mutable drawable is guaranteed to not share its state with any other drawable. This is especially useful when you need to modify properties of drawables loaded from resources. By default, all drawables instances loaded from the same resource share a common state; if you modify the state of one instance, all the other instances will receive the same modification.Calling this method on a mutable Drawable will have no effect.
上述解释的很清楚,一个drawable若是使用了mutate()方法,那么对这个drawable属性(包括设置drawable的透明度)修改将不会共享。
mImageView.setBackgroundDrawable(mDrawable); mImageView.getBackground().setAlpha(100);
上述代码有问题吗?
“确定没有额,经过这种方式透明度没有问题额,亲试可用”。若是你所使用的mDrawable是图片资源(ColorDrawable 中使用了mutate方法),并且多处使用,你就会发现,其余地方透明度也变了。
上述代码正确写法:
mImageView.setBackgroundDrawable(mDrawable.mutate()); mImageView.getBackground().setAlpha(100);
经过上面的分析可知,设置ImageView的透明度,坑仍是至关多的,目前来看使用View提供的setAlpha(float alpha)更好。
有时候设计须要在ImageView 上面覆盖一层(如灰色),面对这样的需求时,要区分是静态的ImageView仍是异步的ImageView (使用后台回包数据)。
合理使用src (前景)和background(背景)就能够实现
此就须要使用ImageView的前景(View 提供了一个setForeground(Drawable foreground))
图5 View的setForeground()方法
图 6 view的构造函数中mForegroundInfo对象建立
根据上述源码可知,若是ImageView要使用setForeground()方法,必须保证targetSdkVersion>=23。
若是此时要在targetSdkVersion<23状况使用,就必须本身去实现,好在afc框架中ExtendImageView已经考虑到这种状况,已经实现了setForeFround()方法。
adjustViewBounds的介绍以下:
Set this to true if you want the ImageView to adjust its bounds to preserve the aspect ratio of its drawable.
Note:If the application targets API level 17 or lower, adjustViewBounds will allow the drawable to shrink the view bounds, but not grow to fill available measured space in all cases.This is for compatibility with legacy MeasureSpec and RelativeLayout behavior.
设置View的最大高度,单独使用无效,须要与setAdjustViewBounds一块儿使用;若是想设置图片固定大小,又想保持图片宽高比,须要以下设置:
设置setAdjustViewBounds为true;
设置maxWidth、MaxHeight;
设置设置layout_width和layout_height为wrap_content
如前所说,ImageView的“android:scaleType”属性是对src才有效的,以下图所示,须要对下面原图进行缩放控制,效果以下:
设计大大以为不合理,要是图片总体能下来一点点就行了,查看一遍ScaleType,能到达这样效果的只有FIT_XY,那就试试看
图片确实下移了,可是图却明显的被拉长了
ScaleDrawable类是afc框架中提供了一个专门处理Drawable scale的类,在ImageView的ScaleType的基础上额外提供了11中裁剪方式:
(1)CROP_CENTER (2)CROP_START (3)CROP_END (4)FIT_CENTER (5)FIT_START (6)FIT_END (7)MATCH_WIDTH_TOP (8)MATCH_WIDTH_BOTTOM (9)MATCH_WIDTH_CENTER (10)CENTER (11)CROP_BY_PIVOT
xml中设置scaleType属性
java代码中设置ScaleDrawable.CROP_START属性
看到上述代码,有人可能以为很疑惑,既然在java代码中设置了ScaleDrawable.CROP_START属性,为何XML中还要设置“android:scaleType="fitXY”,可否不设置或者设置其余属性。
答案是否认的,若是要保证ScaleDrawable.CROP_START属性设置成功,在xml中必定要设置“android:scaleType="fitXY”,缘由以下:
setScaleType()方法
updateDrawMatrix()方法
能够看到,若是要ScaleDrawable.CROP_START属性设置起做用,那个getBounds()方法获取必定要准确。
configBounds()方法
本人能力有限,分析可能不到位或错误的地方,若是发现,请告知谢谢!
更多精彩内容欢迎关注bugly的微信公众帐号:
腾讯 Bugly是一款专为移动开发者打造的质量监控工具,帮助开发者快速,便捷的定位线上应用崩溃的状况以及解决方案。智能合并功能帮助开发同窗把天天上报的数千条 Crash 根据根因合并分类,每日日报会列出影响用户数最多的崩溃,精准定位功能帮助开发同窗定位到出问题的代码行,实时上报能够在发布后快速的了解应用的质量状况,适配最新的 iOS, Android 官方操做系统,鹅厂的工程师都在使用,快来加入咱们吧!