Android ImageView 正確使用姿勢

一、正確合理使用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)方法

圖1 ImageView 的setAlpha()

(2)通過applyColorMod方法可知,ImageView.setAlpha(int alpha)方法,是通過Drawable.setAlpha(int alpha)實現的

圖2 ImageView的applyColorMod()

那么mDrawable 是怎樣得到的了:

圖3 ImageView構造函數 獲取src設置的圖片

? ? ? ?setImageDrawable(Drawable d) 中調用 updateDrawable(Drawable d),而mDrawable 正是在updateDrawable(Drawable d)中賦值的:

圖4 ImageView的updateDrawable()方法

? ? ? ?現在知道為什么有時候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))

圖5 View的setForeground()方法
圖 6 view的構造函數中mForegroundInfo對象創建

? ? ? ? ?根據上述源碼可知,如果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

CENTER_CORP 模式

? ? ? ?設計大大覺得不合理,要是圖片整體能下來一點點就好了,查看一遍ScaleType,能到達這樣效果的只有FIT_XY,那就試試看

(2)使用ScaleType.FIT_XY

FIT_XY模式

? ? ? ? ? 圖片確實下移了,但是圖卻明顯的被拉長了?

(3)使用ScaleDrawable.CROP_START

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"屬性

xml中設置scaleType屬性
java代碼中設置ScaleDrawable.CROP_START屬性

? ? ? ?看到上述代碼,有人可能覺得很疑惑,既然在java代碼中設置了ScaleDrawable.CROP_START屬性,為什么XML中還要設置“android:scaleType="fitXY”,能否不設置或者設置其他屬性。

? ? ? ?答案是否定的,如果要保證ScaleDrawable.CROP_START屬性設置成功,在xml中一定要設置“android:scaleType="fitXY”,原因如下:

1)通過ScaleDrawable設置scaleType

setScaleType()方法

2)在updateDrawMatrix()中更新目的寬高 (dstWidth和dstHeight)

updateDrawMatrix()方法

? ? ? ?可以看到,如果要ScaleDrawable.CROP_START屬性設置起作用,那個getBounds()方法獲取一定要準確。

3)通過查看ImageView中的configBounds()方法可知,在dwith和dheight(原圖Drawable的寬高)都不為0的情況下,如果要使用vwidth和vheight,則ImageView的ScaleType必須設置為ScaleType.FIT_XY

configBounds()方法

總結


本人能力有限,分析可能不到位或錯誤的地方,如果發現,請告知謝謝!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,119評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,382評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,038評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,853評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,616評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,112評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,192評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,355評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,869評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,727評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,928評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,467評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,165評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,570評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,813評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,585評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,892評論 2 372

推薦閱讀更多精彩內容