一、正確合理使用ImageView 的src 和background
src :為ImageView 原圖內容,存放原圖大小,不會被拉伸;
background:為Imageview的背景,會根據ImageView給定的長寬進行拉伸;
在ImageView中,可以同時設置src和background屬性(為了減少繪制,可以根據使用場景來設置相應屬性); 由于src中存放的是原圖大小,如果需要對其縮放,就需要使用android:scaleTyle這個屬性(scaleType 只對src屬性有效),另外還可以對background設置透明度。
二、正確設置Imageview的透明度
設置ImageView的透明度有啥正確不正確的,如直接就mImageView.setAlpha(100),不就行了嗎?(答案是不確定,后續分析)
ImageView 設置透明度主要有以下三種方法:
(1)setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) (View提供)
(2)setAlpha(int alpha)? (已經標記為@Deprecated)
(3)setImageAlpha(int alpha) (API>=16)
? ? ? ?其中,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)setAlpha(int alpha)方法
(2)通過applyColorMod方法可知,ImageView.setAlpha(int alpha)方法,是通過Drawable.setAlpha(int alpha)實現的
那么mDrawable 是怎樣得到的了:
? ? ? ?setImageDrawable(Drawable d) 中調用 updateDrawable(Drawable d),而mDrawable 正是在updateDrawable(Drawable d)中賦值的:
? ? ? ?現在知道為什么有時候ImageView.setAlpha(int alpha)沒起作用了吧。
(3)在applyColorMod()中為什么使用Drawable.mutate()方法
直接引用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);
(4)總結
? ? ? ? 通過上面的分析可知,設置ImageView的透明度,坑還是相當多的,目前來看使用View提供的setAlpha(float alpha)更好。
三、正確設置ImageView的前景(foreground)
? ? ? ? 有時候設計需要在ImageView 上面覆蓋一層(如灰色),面對這樣的需求時,要區分是靜態的ImageView還是異步的ImageView (使用后臺回包數據)。
(1)靜態ImageView (此場景基本很少,設計切圖即可)
? ? ? ?合理使用src (前景)和background(背景)就可以實現?
(2)異步ImageView
? ? ? ?此就需要使用ImageView的前景(View 提供了一個setForeground(Drawable foreground))
? ? ? ? ?根據上述源碼可知,如果ImageView要使用setForeground()方法,必須保證targetSdkVersion>=23。
? ? ? ? 如果此時要在targetSdkVersion<23情況使用,就必須自己去實現,好在afc框架中ExtendImageView已經考慮到這種情況,已經實現了setForeFround()方法。
四、正確使用ImageView的“android:adjustViewBounds”
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一起使用;如果想設置圖片固定大小,又想保持圖片寬高比,需要如下設置:
(1) 設置setAdjustViewBounds為true;
(2)設置maxWidth、MaxHeight;
(3) 設置設置layout_width和layout_height為wrap_content
五、正確使用ImageView的“android:scaleType”
? ? ? ?如前所說,ImageView的“android:scaleType”屬性是對src才有效的,如下圖所示,需要對下面原圖進行縮放控制,效果如下:
(1)原圖
(2)使用ScaleType.CENTER_CORP
? ? ? ?設計大大覺得不合理,要是圖片整體能下來一點點就好了,查看一遍ScaleType,能到達這樣效果的只有FIT_XY,那就試試看
(2)使用ScaleType.FIT_XY
? ? ? ? ? 圖片確實下移了,但是圖卻明顯的被拉長了?
(3)使用ScaleDrawable.CROP_START
? ? ? 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
(4)XML設置android:scaleType="fitXY"屬性
? ? ? ?看到上述代碼,有人可能覺得很疑惑,既然在java代碼中設置了ScaleDrawable.CROP_START屬性,為什么XML中還要設置“android:scaleType="fitXY”,能否不設置或者設置其他屬性。
? ? ? ?答案是否定的,如果要保證ScaleDrawable.CROP_START屬性設置成功,在xml中一定要設置“android:scaleType="fitXY”,原因如下:
1)通過ScaleDrawable設置scaleType
2)在updateDrawMatrix()中更新目的寬高 (dstWidth和dstHeight)
? ? ? ?可以看到,如果要ScaleDrawable.CROP_START屬性設置起作用,那個getBounds()方法獲取一定要準確。
3)通過查看ImageView中的configBounds()方法可知,在dwith和dheight(原圖Drawable的寬高)都不為0的情況下,如果要使用vwidth和vheight,則ImageView的ScaleType必須設置為ScaleType.FIT_XY
總結
本人能力有限,分析可能不到位或錯誤的地方,如果發現,請告知謝謝!