AndroidAutoLayout的簡(jiǎn)單閱讀

? ? ? 前段時(shí)間hongyang大神發(fā)布了一個(gè)庫(kù)暂幼,AndroidAutoLayout藐窄。該庫(kù)的使用贮泞,是用戶(該庫(kù)的使用者递瑰,即,猿們)告訴app,設(shè)計(jì)圖的寬和高為多少像素隙畜,然后在UI布局里直接使用px作為單位抖部,該庫(kù)會(huì)自動(dòng)將填寫的px值轉(zhuǎn)換為屏幕的百分比值,以此來(lái)完成適配议惰。

? ? 該庫(kù)的使用方式有兩種慎颗,一種是直接將Activity extends AutoLayoutActivity,另一種是在布局文件里使用該庫(kù)提供的三個(gè)代替LinearLayout, FrameLayout, RelativeLayout的AutoLinearLayout, AutoFrameLayout, AutoRelativeLayout控件.

? ? ?如果是使用直接繼承AutoLayoutActivity的方法言询,這個(gè)相當(dāng)省事俯萎。其實(shí)現(xiàn)是:在AutoLayoutActivity類內(nèi)部重寫了onCreateView(),這個(gè)方法會(huì)在Activity的onCreate()之后調(diào)用运杭,onCreateView調(diào)用完畢才調(diào)用Activity生命周期函數(shù)onStart().

? ? ? 這是它在Activity源碼中的說(shuō)明夫啊,默認(rèn)實(shí)現(xiàn)是返回null,它是LayoutInflater.Factory#onCreateView()的實(shí)現(xiàn)辆憔。

? ? ? ?而Factory是LayoutInflater中的一個(gè)接口

? ? ?在這個(gè)方法傳進(jìn)來(lái)的參數(shù)中的name是每一個(gè)View(放在布局文件中的View)的名字撇眯,比如LinearLayout, FrameLayout,TextView。

? ? ?在Activity中onCreateView()會(huì)被調(diào)用多次虱咧,順序是LinearLayout , ViewStub ,FrameLayout(這個(gè)就是ContentFrameLayout)熊榛,之后就是我們寫在xml里的View了,所以在這里我們能拿到寫在xml文件里的控件名字腕巡。

? ? ?LayoutInflater創(chuàng)建View的方法是createView()玄坦,其流程是:從xml中解析出來(lái)信息后,判斷是否帶包名绘沉,如果沒(méi)帶包名就給name拼接上前綴(也就是系統(tǒng)的包名煎楣,例如TextView變成android.widget.TextView),帶包名的(使用自定義View车伞,擴(kuò)展包View的時(shí)候要帶包名)就不需要加前綴择懂。拿到了這個(gè)View的包名+類名,類加載器加載class帖世,取得構(gòu)造方法休蟹,將View new出來(lái)沸枯。

? ? 而如果onCreateView返回的不是null,而是一個(gè)View赂弓,就不會(huì)走createView()绑榴。

? ? 作者就是在AutoLayoutActivity中重寫了該方法,并判斷如果是LinearLayout盈魁,就返回該庫(kù)里的AutoLinearLayout翔怎。RelativeLayout,F(xiàn)rameLayout同上杨耙。如此便做到了偷梁換柱的效果赤套,我們?cè)趚ml里使用的是LinearLayout,但實(shí)際生成的AutoLinearLayout珊膜。

? ? ? 而用戶不是選擇使用Activity extends AutoLayoutActivity這種方式容握,而是在xml文件里直接寫上包名+AutoXXXLayout,額车柠。剔氏。。這里好像沒(méi)什么好說(shuō)的竹祷。


? ? ? 接下來(lái)谈跛,我們來(lái)看該庫(kù)的自動(dòng)布局類,這里分析AutoFrameLayout塑陵,其余兩個(gè)類似感憾。

? ? ? 先說(shuō)下背景,由于我們已經(jīng)告訴app我們?cè)O(shè)計(jì)圖的大小了(該庫(kù)的使用條件之一令花,在Manifest.xml中添加meta阻桅,兩個(gè)字段design_width,design_height),程序就能拿到設(shè)計(jì)圖的寬高(單位為像素)彭则,而設(shè)備的屏幕寬高我們也是可以拿到的鳍刷。當(dāng)我們?cè)诓季治募飳iew的屬性值設(shè)為像素值時(shí)占遥,自然就可以通過(guò)換算得到實(shí)際上在不同的屏幕上該占多少百分比的像素了俯抖。以寬為例:

(edit_width / design_width)* screen_width 這個(gè)結(jié)果就是控件實(shí)際上的像素值。edit_width是用戶填寫的px值瓦胎。這部分代碼就不分析了芬萍。

? ? ? 既然已經(jīng)把FrameLayout偷梁換柱成我們自己的View(AutoFrameLayout)了,那么就可以拿到布局文件時(shí)寫的各個(gè)值(包括自定義屬性搔啊,系統(tǒng)屬性)柬祠。

作者在AutoFrameLayout中主要的代碼是:

重寫generateLayoutParams(),讓該ViewGroup中的每一個(gè)View的LayoutParams變成該類的靜態(tài)內(nèi)部類LayoutParams负芋。

而在onMeasure()方法中借由AutoLayoutHelper來(lái)調(diào)整每一個(gè)子View的屬性(該庫(kù)支持9個(gè)屬性)漫蛔。

? ? ?而在AutoFrameLayout.LayoutParams類中會(huì)把該庫(kù)現(xiàn)有兩個(gè)自定義屬性(basewidth,baseheight),和9個(gè)支持的系統(tǒng)屬性的值拿出來(lái),然后將2個(gè)自定義屬性和9個(gè)屬性值放在AutoFrameLayout.LayoutParams的成員變量AutoLayoutInfo中莽龟,并提供getter蠕嫁。

? ? ? 這里有一點(diǎn)需要提一下,在記錄過(guò)程中毯盈,只有屬性是以“px”結(jié)尾的屬性才會(huì)被記錄下來(lái)剃毒。也就是說(shuō),如果你在AutoFrameLayout中某個(gè)View某個(gè)屬性不想使用這個(gè)百分比自動(dòng)布局的功能搂赋,只要不把屬性寫成px的就行了赘阀。(我在用這個(gè)庫(kù)的時(shí)候,有一個(gè)View的寬屬性無(wú)法事前確定脑奠,只能wrap_content基公。還在想該庫(kù)是不是可以提供一個(gè)自定義屬性ignore可以讓該View免于自動(dòng)布局,看了代碼才知道作者早就設(shè)計(jì)好了)

下面是adjustChildren()的代碼:

? ? ? 作者先做了一次檢查宋欺,checkParams()酌媒,如果用戶沒(méi)有在Manifest.xml中提供design_width,design_height會(huì)報(bào)錯(cuò)迄靠。

? ? ?之后就是拿到mHost(AutoXXXLayout)中的每一個(gè)View的LayoutParams秒咨,取出之前記錄了自定義屬性和屬性值的AutoLayoutInfo,然后將里面的每一個(gè)屬性作用到View上掌挚。這樣就完成了View屬性的更改雨席。

? ? ?該庫(kù)提供兩個(gè)自定義屬性layout_auto_basewidth, layout_auto_baseheight。由于手機(jī)屏幕的碎片化(Android手機(jī)你懂的)吠式,比如想讓一個(gè)ImageView的寬高一致時(shí)陡厘,寫寬20px,高20px特占,經(jīng)過(guò)百分比換算屏幕大小糙置,很可能就不一致了。所以需要一個(gè)單位基準(zhǔn)是目,比如寬20px谤饭,高20px,layout_auto_basewidth=height懊纳,那么高度就會(huì)以width為基準(zhǔn)了揉抵,其換算公式是(edit_height/design_width) * screen_width。如此嗤疯,這個(gè)ImageView的寬高就一樣大小了冤今,正方形。

? ? AutoAttr這個(gè)類茂缚,作者用來(lái)封裝每一個(gè)屬性值的信息戏罢,多少px屋谭,以哪個(gè)方向(寬,高)為基準(zhǔn)龟糕。如果我們?cè)趚ml里沒(méi)有指定某屬性的基準(zhǔn)戴而,就會(huì)使用該屬性的默認(rèn)基準(zhǔn)。默認(rèn)基準(zhǔn)是翩蘸,豎直方向上以高為基準(zhǔn)所意,水平方向以寬為基準(zhǔn)。即:marginTop以height為基準(zhǔn)催首,marginLeft以width為基準(zhǔn)扶踊,textSize以height為基準(zhǔn),其他的同上郎任。

? ? 最后秧耗,如果換算出來(lái)不足1px,以1px返回舶治。

AutoAttr的apply()方法代碼如下:

? ? 以上是我對(duì)AndroidAutoLayout的理解分井,如果錯(cuò)了,還請(qǐng)指正霉猛,謝謝尺锚。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市惜浅,隨后出現(xiàn)的幾起案子瘫辩,更是在濱河造成了極大的恐慌,老刑警劉巖坛悉,帶你破解...
    沈念sama閱讀 211,884評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件伐厌,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡裸影,警方通過(guò)查閱死者的電腦和手機(jī)挣轨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,347評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)轩猩,“玉大人卷扮,你說(shuō)我怎么就攤上這事〗缧” “怎么了画饥?”我有些...
    開(kāi)封第一講書人閱讀 157,435評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)浊猾。 經(jīng)常有香客問(wèn)我,道長(zhǎng)热鞍,這世上最難降的妖魔是什么葫慎? 我笑而不...
    開(kāi)封第一講書人閱讀 56,509評(píng)論 1 284
  • 正文 為了忘掉前任衔彻,我火速辦了婚禮,結(jié)果婚禮上偷办,老公的妹妹穿的比我還像新娘艰额。我一直安慰自己,他們只是感情好椒涯,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,611評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布柄沮。 她就那樣靜靜地躺著,像睡著了一般废岂。 火紅的嫁衣襯著肌膚如雪祖搓。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 49,837評(píng)論 1 290
  • 那天湖苞,我揣著相機(jī)與錄音拯欧,去河邊找鬼。 笑死财骨,一個(gè)胖子當(dāng)著我的面吹牛镐作,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播隆箩,決...
    沈念sama閱讀 38,987評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼该贾,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了捌臊?” 一聲冷哼從身側(cè)響起靶庙,我...
    開(kāi)封第一講書人閱讀 37,730評(píng)論 0 267
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎娃属,沒(méi)想到半個(gè)月后六荒,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,194評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡矾端,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,525評(píng)論 2 327
  • 正文 我和宋清朗相戀三年掏击,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片秩铆。...
    茶點(diǎn)故事閱讀 38,664評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡砚亭,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出殴玛,到底是詐尸還是另有隱情捅膘,我是刑警寧澤,帶...
    沈念sama閱讀 34,334評(píng)論 4 330
  • 正文 年R本政府宣布滚粟,位于F島的核電站寻仗,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏凡壤。R本人自食惡果不足惜署尤,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,944評(píng)論 3 313
  • 文/蒙蒙 一耙替、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧曹体,春花似錦俗扇、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,764評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至串稀,卻和暖如春除抛,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背厨诸。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,997評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工镶殷, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人微酬。 一個(gè)月前我還...
    沈念sama閱讀 46,389評(píng)論 2 360
  • 正文 我出身青樓绘趋,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親颗管。 傳聞我的和親對(duì)象是個(gè)殘疾皇子陷遮,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,554評(píng)論 2 349

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