你真的了解 ImageView 的 adjustViewBounds 屬性嗎风瘦?

前言

在 Android 開發(fā)中队魏,如果我們不確定圖片的寬高,又想讓 ImageView 以固定的寬度或高度顯示万搔,且圖片寬高比保持不變胡桨,我們很容易想到 adjustViewBounds 這個(gè)屬性,配合固定的 ImageView 寬度或高度瞬雹,即可實(shí)現(xiàn)寬/高固定昧谊,另一邊自適應(yīng)。

起因

有一個(gè)即時(shí)通信產(chǎn)品酗捌,Emoji 表情通過服務(wù)端接口下發(fā)資源揽浙,支持動(dòng)態(tài)增刪,同時(shí)本地有一份兜底數(shù)據(jù)意敛,用于網(wǎng)絡(luò)不可用時(shí)的兜底展示馅巷。有一天產(chǎn)品在后臺(tái)新增了幾個(gè)表情,測(cè)試發(fā)現(xiàn)個(gè)別手機(jī)上新上的表情顯示比較小草姻,而本地兜底的表情則顯示正常钓猬。

image.png

這里的表情面板使用 RecyclerView 實(shí)現(xiàn),Emoji Item 使用 RelativeLayout 作為容器撩独,Emoji 圖片使用 ImageView 固定高度敞曹,通過 adjustViewBounds 使寬度根據(jù)圖片寬高比自適應(yīng)展示。

復(fù)現(xiàn)

排查過程比較曲折综膀,這里直接嘗試復(fù)現(xiàn)澳迫。

新建一個(gè)布局文件,加入一個(gè) ImageView剧劝,高度固定150dp橄登,大于圖片高度,設(shè)置 adjustViewBoundstrue

image.png

嗯讥此,沒什么問題拢锹,圖片被等比例拉伸,ImageView 的寬度也自適應(yīng)了萄喳,符合對(duì) adjustViewBounds 的預(yù)期卒稳。

接下來,在 ImageView 外層嵌套一層 RelativeLayout

image.png

WTF! 意想不到的事情發(fā)生了他巨,圖片沒有按照預(yù)期的寬高比進(jìn)行拉伸充坑,僅僅展示了原本的尺寸减江,就好像 adjustViewBounds 從來都不存在一樣!

原因

先看一下 ImageView 的測(cè)量方法捻爷,為了方便閱讀辈灼,代碼做了簡(jiǎn)化。

image.png

ImageView 的測(cè)量并不復(fù)雜役衡,大致可以分為以下幾步:

  1. 判斷是否設(shè)置 adjustViewBounds茵休,如果設(shè)置,繼續(xù)往下手蝎,否則使用常規(guī)測(cè)量方法(即使用 Drawable 寬高榕莺、最小寬高和 background 寬高的最大值)
  2. 根據(jù)測(cè)量模式判斷是否可以調(diào)整寬度或高度,如果可以棵介,繼續(xù)往下钉鸯,否則使用常規(guī)測(cè)量方法
  3. 取得 Drawable 寬高和 View 最大寬高的最小值,得到實(shí)際寬高比邮辽,判斷實(shí)際寬高比和 Drawable 是否相同唠雕,如果相同,則使用當(dāng)前寬高吨述,測(cè)量結(jié)束岩睁,否則繼續(xù)
  4. 根據(jù) Drawable 寬高比調(diào)整實(shí)際寬高,使用調(diào)整后的寬高作為測(cè)量結(jié)果揣云,測(cè)量結(jié)束

并沒有看出什么端倪捕儒,看來問題可能不在 ImageView 這里,那就只剩 RelativeLayout 這個(gè)“嫌疑人”了邓夕。

繼續(xù)查看 RelativeLayout 的測(cè)量方法刘莹。

RelativeLayout 的測(cè)量方法就復(fù)雜多了,這里摘出關(guān)鍵代碼

image.png

可以看出焚刚,RelativeLayout 會(huì)對(duì)子 View 測(cè)量?jī)纱蔚阃洌谝淮螠y(cè)量水平方向,確定子 View 的寬度矿咕,第二次抢肛,使用上次測(cè)量的寬度,再次測(cè)量痴腌,得到子 View 實(shí)際的尺寸雌团。

這里沒看出什么問題,繼續(xù)看 measureChildHorizontal 方法

image.png

真相終于浮出眼前士聪!

注意看14-18行,在確定高度測(cè)量模式時(shí)猛蔽,如果高度是 MATCH_PARENT剥悟,則使用 EXACTLY 模式灵寺,否則使用 AT_MOST 模式。

由于我們 ImageView 是固定高度区岗,即固定值略板,因此會(huì)使用 AT_MOST 模式進(jìn)行測(cè)量,而寬度也是
AT_MOST慈缔,回憶一下上面 ImageView 的測(cè)量方法叮称,如果寬高都是 AT_MOST,則實(shí)際大小和 Drawable 一致藐鹤,即第一次測(cè)量的寬度是 Drawable 的實(shí)際寬度瓤檐。

那高度怎么不是 Drawable 的高度呢?因?yàn)?RelativeLayout 第一次測(cè)量只是確定了 ImageView 的寬度娱节,第二次又根據(jù) ImageView 的實(shí)際高度進(jìn)行測(cè)量挠蛉,因此便出現(xiàn)了上圖的情況,即 adjustViewBounds 失效了肄满。

既然 RelativeLayout 是先測(cè)量寬度谴古,那我把寬度固定,高度改為 WRAP_CONTENT稠歉,是不是就沒問題了掰担,沒錯(cuò),我們修改代碼測(cè)試一下

image.png

到這里怒炸,我們基本理清了 RelativeLayout 的測(cè)量方式對(duì) ImageViewadjustViewBounds 屬性的影響带饱,最后我們回到業(yè)務(wù)上,為什么只有新上的表情(通過接口獲群崦摹)顯示偏小纠炮,而內(nèi)置圖片確能正常顯示呢?

原因是內(nèi)置圖片的尺寸放在對(duì)應(yīng) dpi 目錄下灯蝴,會(huì)根據(jù)設(shè)備 dpi 進(jìn)行縮放恢口,因此即使 adjustViewBounds 失效,也能拉伸到對(duì)應(yīng)尺寸穷躁,因此顯示正常耕肩,而通過接口下載的圖片,density 默認(rèn)和設(shè)備一致问潭,因此在 density 比較高的設(shè)備上猿诸,無法自動(dòng)拉伸到預(yù)期的尺寸。

解決

弄清楚了問題的原因就很容易解決了狡忙,這里 Emoji 容器中只有一個(gè) ImageView 保持居中梳虽,不依賴 RelativeLayout 的特性,因此直接替換為 FrameLayout 即可灾茁。

總結(jié)

本文主要通過一個(gè)業(yè)務(wù) bug窜觉,通過源碼解讀谷炸,發(fā)現(xiàn) ImageViewRelativeLayout 組合使用,在特定場(chǎng)景下 adjustViewBounds 屬性會(huì)“失效”的問題禀挫,最終通過替換為 FrameLayout 來解決旬陡。

不清楚這個(gè)問題是 Google 是有意為之,還是一個(gè) Bug语婴,目前官方文檔上暫時(shí)未發(fā)現(xiàn)有相關(guān)說明描孟,有了解的大佬可以幫小弟解解惑。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末砰左,一起剝皮案震驚了整個(gè)濱河市匿醒,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌菜职,老刑警劉巖青抛,帶你破解...
    沈念sama閱讀 216,496評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異酬核,居然都是意外死亡蜜另,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門嫡意,熙熙樓的掌柜王于貴愁眉苦臉地迎上來举瑰,“玉大人,你說我怎么就攤上這事蔬螟〈搜福” “怎么了?”我有些...
    開封第一講書人閱讀 162,632評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵旧巾,是天一觀的道長(zhǎng)耸序。 經(jīng)常有香客問我,道長(zhǎng)鲁猩,這世上最難降的妖魔是什么坎怪? 我笑而不...
    開封第一講書人閱讀 58,180評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮廓握,結(jié)果婚禮上搅窿,老公的妹妹穿的比我還像新娘。我一直安慰自己隙券,他們只是感情好男应,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著娱仔,像睡著了一般沐飘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上牲迫,一...
    開封第一講書人閱讀 51,165評(píng)論 1 299
  • 那天薪铜,我揣著相機(jī)與錄音众弓,去河邊找鬼恩溅。 笑死隔箍,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的脚乡。 我是一名探鬼主播蜒滩,決...
    沈念sama閱讀 40,052評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼奶稠!你這毒婦竟也來了俯艰?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,910評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤锌订,失蹤者是張志新(化名)和其女友劉穎竹握,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體辆飘,經(jīng)...
    沈念sama閱讀 45,324評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡啦辐,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蜈项。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片芹关。...
    茶點(diǎn)故事閱讀 39,711評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖紧卒,靈堂內(nèi)的尸體忽然破棺而出侥衬,到底是詐尸還是另有隱情,我是刑警寧澤跑芳,帶...
    沈念sama閱讀 35,424評(píng)論 5 343
  • 正文 年R本政府宣布轴总,位于F島的核電站,受9級(jí)特大地震影響博个,放射性物質(zhì)發(fā)生泄漏怀樟。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評(píng)論 3 326
  • 文/蒙蒙 一坡倔、第九天 我趴在偏房一處隱蔽的房頂上張望漂佩。 院中可真熱鬧,春花似錦罪塔、人聲如沸投蝉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瘩缆。三九已至,卻和暖如春佃蚜,著一層夾襖步出監(jiān)牢的瞬間庸娱,已是汗流浹背着绊。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留熟尉,地道東北人归露。 一個(gè)月前我還...
    沈念sama閱讀 47,722評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像斤儿,于是被迫代替她去往敵國(guó)和親剧包。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容