Android基礎 - 如何做魯棒性更高的布局

前情提要

這是一篇寫給入坑Android開發(fā)新手的文章秋柄,它可能不太適合老手閱讀,也可能帶有一些我個人的理解和見地帝蒿,但我是衷心希望更多的新人開發(fā)者能從這篇文章中獲取知識盅蝗,讓我們一同進步。當然了尤蛮,其中可能不可避免的會存在一些遺漏和錯誤媳友,也希望大家多多指正。

目錄

· 什么是布局&盒子模型
· 盡可能使用LinearLayout構建布局
· 顱內秒建模产捞,指哪打哪
· 還有被遺忘的圖片兄弟咋辦呀醇锚?

什么是布局&盒子模型

移動智能設備是目前最火的人機交互設備之一,應市場的召喚坯临,作為開發(fā)者的我們想要在這樣的設備中開發(fā)出優(yōu)質的作品那么就需要讓我們的產品具備更好的視覺和功能體驗焊唬,而布局,正是構建視覺體驗的基礎看靠。良好的布局構建可以幫助我們更快赶促、更好的完成一個應用視覺開發(fā),那么將UI產出的圖形稿件變現(xiàn)成為可以操作的APP界面挟炬,我們就應該能夠完成魯棒性更高的布局開發(fā)鸥滨。

布局開發(fā)是APP前端開發(fā)中最重要的一環(huán),而目前我們所做的大部分APP開發(fā)離不開一種模型谤祖,即盒子模型婿滓,字面意思理解,就是一個盒子套一個盒子粥喜,外邊的盒子位置的變動里邊的小盒子也會跟著變凸主,反映到布局上,即父布局和子布局额湘,但是注意了卿吐,在Android提供的基礎組件中旁舰,有些組件可以構成所謂的“盒子”,而有些組件則不行嗡官,他們只能作為放在盒子內部拿來使用的存在箭窜。典型的“盒子”即繼承自父類“ViewGroup”的相對布局RelativeLayout以及線性布局LinearLayout,當然了還有滾動布局ScrollView衍腥、網格布局GridLayout等十分的多绽快,而我們日常使用到的按鈕Button、圖像ImageView紧阔、文本TextView則不是“盒子”了,他們只能作為子布局放在盒子內续担,以上擅耽,就是盒子模型的簡單陳述了。

盡可能使用LinearLayout構建布局

相對布局RelativeLayout可能是新手入坑Android開發(fā)后最常用的布局物遇,因為其跟我們日常所理解的畫布類似乖仇,我們想將哪個部件放在畫布的哪個位置都是非常自由的,但事實上询兴,從結構的完整性上講乃沙,RelativeLayout并不是真正適合作為布局主體進行布局構建方式,雖然看似其十分好用诗舰,但實際上當我們將作為底子的畫布變換一個方向和大小警儒,可能就沒那么方便了:

使用RelativeLayout構建的布局.png

這可能會直接導致界面混亂,以至于出現(xiàn)“換了個手機就不能用了”的尷尬情況眶根,那么如何避免此類問題呢蜀铲?事實上,可能讓我們覺得并不好用的LinearLayout就可以幫我們更好的解決這個問題属百。

使用LinearLayout構建的布局沒有問題.png

使用LinearLayout布局可以更加方便的完成如上圖所示的布局记劝,但在此之前,我們需要明白一個在LinearLayout布局中的子布局特有的屬性:layout_weight族扰,當一個子布局放在LinearLayout中的時候厌丑,layout_weight屬性即可使用,它的意義在于“權重”渔呵,在線性布局中怒竿,子布局都是按照從上到下、從左到右來排列的厘肮,但當子布局的寬度或高度為match_parent愧口,即占滿父布局的全部寬高度時,這里就會存在一個問題类茂,其他的子布局會被擠出屏幕外耍属,此時要讓他們“平均”顯示托嚣,就需要一個參數(shù)layout_weight了,將所有子布局設置layout_weight="1"厚骗,你就會發(fā)現(xiàn)他們在父布局中被等分寬高了示启,利用這個特性原理來構建布局則可以輕松做到健壯性更高不具效果而不需要擔心很多界面重疊、錯位的問題:

相對布局和線性布局.png

我個人相對更推薦線性布局為主進行主體布局的開發(fā)领舰,這樣可以規(guī)避掉很多問題夫嗓,提升布局的魯棒性。具體表現(xiàn)在哪里呢冲秽?看下邊這個截圖:

要實現(xiàn)的效果.png

我們要實現(xiàn)上邊的這個效果舍咖,用相對布局的代碼如下:

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal">

        <Button
            android:layout_width="70dp"
            android:layout_height="70dp"
            android:text="1" />

        <Button
            android:id="@+id/button2"
            android:layout_width="70dp"
            android:layout_height="70dp"
            android:layout_alignParentEnd="true"
            android:layout_alignParentRight="true"
            android:layout_alignParentTop="true"
            android:text="2" />

        <Button
            android:id="@+id/button3"
            android:layout_width="70dp"
            android:layout_height="70dp"
            android:layout_below="@+id/button2"
            android:layout_toLeftOf="@+id/button2"
            android:layout_toStartOf="@+id/button2"
            android:text="3" />

    </RelativeLayout>

用線性布局寫的代碼如下:

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <Button
                android:id="@+id/button1"
                android:layout_width="70dp"
                android:layout_height="70dp"
                android:text="1" />

            <View
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:layout_weight="1" />

            <Button
                android:id="@+id/button2"
                android:layout_width="70dp"
                android:layout_height="70dp"
                android:text="2" />

        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <View
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:layout_weight="1" />

            <Button
                android:id="@+id/button3"
                android:layout_width="70dp"
                android:layout_height="70dp"
                android:text="3" />

            <View
                android:layout_width="70dp"
                android:layout_height="70dp" />

        </LinearLayout>
    </LinearLayout>

看似線性布局的代碼多了是不是?那么它的優(yōu)勢到底在哪里呢锉桑?所謂魯棒性排霉,可以理解成可靠性,也于容錯性相關民轴,那么你在下邊的線性布局方案中可有見過一句android:layout_toLeftOf攻柠、android:layout_toStartOf之類的需要綁定其他組件的語句么?這里最關鍵的意義在于后裸,采用線性布局構建的代碼方案中瑰钮,不存在某個子布局組件和其他子布局組件存在關聯(lián)關系的情況,那么這在后期維護項目的過程中微驶,如果出現(xiàn)需要刪除浪谴、隱藏掉其可能存在關聯(lián)關系的布局的情況時,我們的界面不會出現(xiàn)任何錯誤的情況祈搜,其魯棒性遠高于采用相對布局的代碼较店。

如果經歷過大型項目我們都會知道,在大型項目中可能存在大量的布局容燕、組件梁呈,這樣的情況下如果需要對其中某一部分進行修改,那么極可能出現(xiàn)牽一發(fā)而動全身的問題蘸秘,很多問題還不會立刻表現(xiàn)出來官卡,而是會在某些條件達成時出現(xiàn)問題,帶來不良的用戶體驗醋虏,因此寻咒,在日常布局設計時,除了可能存在需要居中某些子布局組件而使用相對布局的情況外颈嚼,我建議能使用線性布局就是用線性布局來進行構建毛秘。

顱內秒建模,指哪打哪

相對一些特殊的應用,我們日常能遇到需要開發(fā)的大多是一些業(yè)務系統(tǒng)叫挟,而這艰匙,更是線性布局的主場了。


一日讀.png

「一日讀」是我開源在Github上的輕圖片抹恳、視頻以及知乎日報功能的客戶端( https://github.com/kongzue/EnjoyLife )员凝,這里就拿它的關于界面來舉例好了,在這個界面中奋献,主體采用了一個頂屏幕寬高的縱向LinearLayout健霹,里邊的圖片、文字都是采用margin的形式進行分隔瓶蚂,而頂部的導航條糖埋,則需要懸浮在主界面之上,那么它則采用了一個橫向的線性布局作為主體設計了返回按鈕窃这、分享按鈕以及標題阶捆,但其中的標題需要居中,則在其上疊加了一層相對布局來完成钦听。

此布局在橫向、各種分辨率(非極端)的情況下均不會出現(xiàn)任何問題倍奢,且因為不存在大量的相對代碼朴上,維護成本更低。

彩蛋·還有被遺忘的圖片兄弟咋辦呀卒煞?

線性布局相對于相對布局確實更具優(yōu)勢痪宰,但在我們開發(fā)過程中也會遇到有一些采用更高分辨率、更奇葩的比例畔裕、或非常見的更高dpi的手機衣撬,此時就可能存在一個問題了,我們可愛好看的背景圖被無情的拉伸了扮饶,那么這種問題如何解決呢具练?

以軟件開屏的閃屏圖為例,在16:9的手機上和19:9的手機上可能出現(xiàn)如下效果:


閃屏圖.png

顯然甜无,我們一般的開發(fā)都是基于16:9的設備進行的扛点,而在全面屏大行其道的今天,出現(xiàn)18:9岂丘,甚至19:9的手機也不足為奇陵究,而這種情況下,我們閃屏頁的布局中廣告圖部分的高度就發(fā)生了變化奥帘,正常方式下要么出現(xiàn)上下白邊铜邮,要么出現(xiàn)被拉伸,那么這里就要用到ImageView的屬性:

android:scaleType="centerInside"

使用此屬性的ImageView會以內等比例頂寬高縮放,以保證圖像能夠占滿布局松蒜,而這里也需要UI小姐姐們在出圖時盡可能避免內容貼邊的情況扔茅,這樣的適配就不會出現(xiàn)問題了。

尾巴

根據(jù)適合的業(yè)務邏輯采用適合的布局架構可以輕松節(jié)省維護成本和構建時間牍鞠,對于軟件的健壯性上都會有不錯的提升咖摹,重復性勞動是我們在開發(fā)過程中最需要避免的,而良好的布局基礎則是軟件能夠運營維護得更長遠的根本难述,此篇文章主要分享的是我在開發(fā)設計布局中的一些見解萤晴,如果不對還希望大家多多指正,也希望大家養(yǎng)成良好的布局習慣胁后,做出更好用的軟件店读。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市攀芯,隨后出現(xiàn)的幾起案子屯断,更是在濱河造成了極大的恐慌,老刑警劉巖侣诺,帶你破解...
    沈念sama閱讀 216,651評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件殖演,死亡現(xiàn)場離奇詭異,居然都是意外死亡年鸳,警方通過查閱死者的電腦和手機趴久,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來搔确,“玉大人彼棍,你說我怎么就攤上這事∩潘悖” “怎么了座硕?”我有些...
    開封第一講書人閱讀 162,931評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長涕蜂。 經常有香客問我华匾,道長,這世上最難降的妖魔是什么机隙? 我笑而不...
    開封第一講書人閱讀 58,218評論 1 292
  • 正文 為了忘掉前任瘦真,我火速辦了婚禮,結果婚禮上黍瞧,老公的妹妹穿的比我還像新娘诸尽。我一直安慰自己,他們只是感情好印颤,可當我...
    茶點故事閱讀 67,234評論 6 388
  • 文/花漫 我一把揭開白布您机。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪际看。 梳的紋絲不亂的頭發(fā)上咸产,一...
    開封第一講書人閱讀 51,198評論 1 299
  • 那天,我揣著相機與錄音仲闽,去河邊找鬼脑溢。 笑死,一個胖子當著我的面吹牛赖欣,可吹牛的內容都是我干的屑彻。 我是一名探鬼主播,決...
    沈念sama閱讀 40,084評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼顶吮,長吁一口氣:“原來是場噩夢啊……” “哼社牲!你這毒婦竟也來了?” 一聲冷哼從身側響起悴了,我...
    開封第一講書人閱讀 38,926評論 0 274
  • 序言:老撾萬榮一對情侶失蹤搏恤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后湃交,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體熟空,經...
    沈念sama閱讀 45,341評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,563評論 2 333
  • 正文 我和宋清朗相戀三年搞莺,在試婚紗的時候發(fā)現(xiàn)自己被綠了痛阻。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,731評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡腮敌,死狀恐怖,靈堂內的尸體忽然破棺而出俏扩,到底是詐尸還是另有隱情糜工,我是刑警寧澤,帶...
    沈念sama閱讀 35,430評論 5 343
  • 正文 年R本政府宣布录淡,位于F島的核電站捌木,受9級特大地震影響,放射性物質發(fā)生泄漏嫉戚。R本人自食惡果不足惜刨裆,卻給世界環(huán)境...
    茶點故事閱讀 41,036評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望彬檀。 院中可真熱鬧帆啃,春花似錦、人聲如沸窍帝。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至疯坤,卻和暖如春报慕,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背压怠。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評論 1 269
  • 我被黑心中介騙來泰國打工眠冈, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人菌瘫。 一個月前我還...
    沈念sama閱讀 47,743評論 2 368
  • 正文 我出身青樓蜗顽,卻偏偏與公主長得像,于是被迫代替她去往敵國和親突梦。 傳聞我的和親對象是個殘疾皇子诫舅,可洞房花燭夜當晚...
    茶點故事閱讀 44,629評論 2 354