16 | 布局設(shè)計:如何將 Flutter 布局設(shè)計沉淀為理論規(guī)范

前面課時只介紹了組件設(shè)計橄碾,并沒有過多涉及布局的講解卵沉,可能你了解一些布局組件,比如 Container法牲、Row史汗、Column、Padding拒垃、Center 等停撞,但是對于如何從 UI 稿到組件再到布局,卻沒有非常清晰的思路悼瓮。本課時就從我的角度來分析戈毒,如何進行組件的布局。

常見布局組件

在 Flutter 中可以分為 Single-child layout widgets 和 Multi-child layout widgets 横堡,使用中文來解釋就是單個子元素的布局組件和多個子元素的布局組件埋市。

Single-child

常見單個子組件的有 Align、Padding翅萤、 Expanded 和 Container 恐疲。

Align 比較好理解,Align 組件的位置左套么、右培己、上、下胚泌、左上省咨、右下、左下玷室、右上零蓉,這兩者一般配合 Container 來使用。

Padding 是一個可以設(shè)置上下和左右填充的組件穷缤,在布局設(shè)計中也非常常見敌蜂。

Expanded 是一個可伸縮的容器,可以根據(jù)子組件的大小進行動態(tài)伸縮津肛,這個需要配合 Row 組件的 flex 布局使用章喉,其次也可以作為動態(tài)列表的父組件,避免列表超出界面,引起布局問題秸脱。

Container 是比較常用的落包,類似一個容器,可以設(shè)置容器的大小摊唇,然后將子元素包裹在容器中咐蝇,該組件在超出容器后,會容易引起布局問題巷查。

Multi-child

常見的多個子組件有 Row有序、Column 和 Stack。

Row 是橫排展示子組件吮便。

Column 是豎排展示子組件笔呀。

Stack 是層疊展示子組件。

以上具體每個組件的參數(shù)配置髓需,大家可以在官網(wǎng)查到许师,官網(wǎng)還有一些不常用的,但也比較實用的布局組件僚匆,這里就不詳細列出了微渠。

布局思想

將布局的思想總結(jié)為八個字:豎、橫咧擂、高逞盆、寬、上松申、下云芦、左、右贸桶。 也就是一個頁面出來以后舅逸,按照這八個字的先后去分析頁面的布局。那么我們具體來看下皇筛,八個字中會涉及哪些布局組件的應(yīng)用琉历。

豎和橫

根據(jù)設(shè)計好的組件樹,從上往下分析水醋,遇到塊狀不同內(nèi)容組旗笔,則設(shè)計為一個 Column 的子元素。例如圖 2 的一個界面拄踪,從上往下分析蝇恶,我們可以得到 6 個 Column 布局組件的子組件(這里為了演示效果,我們把組件也設(shè)計為 6 個部分)惶桐。

圖 1 帖子詳情頁

分析完成以后艘包,我們再來看下每一行組件中所涉及的子組件的猛。行子組件一般也是基于:Container、Row想虎、Center 等布局組件來實現(xiàn)的,根據(jù)圖 1 的效果叛拷,我們來分析:

第一部分是居中的文章標題舌厨,可以使用 Center 組件;

第二部分是一條橫線忿薇,可以使用 Divider 來繪制一條分割直線裙椭;

第三部分是用戶信息,因為橫著是有兩個組件署浩,所以使用 Row揉燃;

第四部分是文章內(nèi)容,這里使用 Container 包裹一個 Text 組件筋栋;

第五部分是文章圖片炊汤,這里也使用 Container 包裹一個 Image 組件;

第六部分是一個組件弊攘,這個組件內(nèi)部豎看也是兩個組件抢腐,因此需要使用 Column 組件。

根據(jù)以上規(guī)則我們就可以設(shè)計出一個 pages 的頁面了襟交,代碼如下:

復(fù)制代碼

return Column(

? children: <Widget>[

? ? ArticleDetailTitle(title: contentDetail.title),

? ? Divider(),

? ? ArticleDetailUserInfoBar(userInfo: contentDetail.userInfo),

? ? ArticleDetailContent(content: contentDetail.detailInfo),

? ? ArticleDetailImg(articleImage: contentDetail.articleImage),

? ? ArticleDetailLike(articleId: id, likeNum: contentDetail.likeNum)

? ],

);

高和寬

接下來我們分析好每個組件所占用的高和寬迈倍,這部分可以在組件的 Container 屬性中設(shè)置,有些組件也自帶高和寬屬性捣域。例如上面的 Divider 組件我們就需要設(shè)置高和寬啼染,代碼如下:

復(fù)制代碼

return Column(

? children: <Widget>[

? ? ArticleDetailTitle(title: contentDetail.title),

? ? Divider(

? ? ? ? height: 1,

? ? ? ? color: Colors.lightBlueAccent,

? ? ? ? indent: 75,

? ? ? ? endIndent: 75

? ? ),

? ? ArticleDetailUserInfoBar(userInfo: contentDetail.userInfo),

? ? ArticleDetailContent(content: contentDetail.detailInfo),

? ? ArticleDetailImg(articleImage: contentDetail.articleImage),

? ? ArticleDetailLike(articleId: id, likeNum: contentDetail.likeNum),

? ? ArticleDetailComments(commentList: [])

? ],

);

上面代碼的第 5 行就是設(shè)置高,第 7 和第 8 行就是設(shè)置其寬度焕梅。

上和下

設(shè)置完每個組件的高和寬后迹鹅,我們再從上往下看。根據(jù)組件樹丘侠,這里主要看 Column 組件下的所有子組件之間是否需要設(shè)置上下徒欣,如果需要則應(yīng)用 Padding 來實現(xiàn)。為了效果蜗字,我們在 ArticleDetailContent 和 ArticleDetailUserInfoBar 之間增加一個 Padding 效果打肝,代碼如下:

復(fù)制代碼

return Column(

? children: <Widget>[

? ? ArticleDetailTitle(title: contentDetail.title),

? ? Divider(

? ? ? ? height: 1,

? ? ? ? color: Colors.lightBlueAccent,

? ? ? ? indent: 75,

? ? ? ? endIndent: 75

? ? ),

? ? ArticleDetailUserInfoBar(userInfo: contentDetail.userInfo),

? ? Padding(padding: EdgeInsets.only(top: 2)),

? ? ArticleDetailContent(content: contentDetail.detailInfo),

? ? ArticleDetailImg(articleImage: contentDetail.articleImage),

? ? ArticleDetailLike(articleId: id, likeNum: contentDetail.likeNum),

? ? ArticleDetailComments(commentList: [])

? ],

);

左和右

整體設(shè)置完成后,我們再來看下組件左右的間隔設(shè)置挪捕。這里主要看 Row 組件下的所有子組件粗梭,檢查是否需要 Padding 屬性。其次判斷 Row 子組件是否需要設(shè)置左右占比级零,如果需要則使用到 flex 布局中的 Expanded 組件断医。比如上面組件中的 ArticleDetailUserInfoBar 需要左右布局設(shè)計滞乙,因此根據(jù)規(guī)則我們看下 ArticleDetailUserInfoBar 的代碼邏輯。具體代碼如下:

復(fù)制代碼

@override

Widget build(BuildContext context) {

? return Container(

? ? color: Colors.white,

? ? padding: EdgeInsets.all(8),

? ? child: Row(

? ? ? mainAxisAlignment: MainAxisAlignment.spaceBetween,

? ? ? children: <Widget>[

? ? ? ? Expanded(

? ? ? ? ? flex: 4,

? ? ? ? ? child: Row(),

? ? ? ? Expanded(

? ? ? ? ? flex: 1,

? ? ? ? ? child: Row(),

? ? ? ],

? ? ),

? );

}

上面的代碼中可以看到該組件使用 Container 包裹鉴嗤,其次使用了 Row 組件斩启,假設(shè)我們 UI 稿中的圖 3 部分是左右 4 : 1 布局,因此在代碼中第 10 行設(shè)置前面組件為 4 醉锅,第 13 行設(shè)置后面組件為 1兔簇。

這樣就完成了外部組件的設(shè)計,以上 6 個組件就可以寫一部分偽代碼去實現(xiàn)了硬耍。外部組件設(shè)計完成后垄琐,我們開始通過 8 個過程來進行子組件布局設(shè)計,對于其中的 8 個過程经柴,并不是每個組件都需要狸窘,因此越到根節(jié)點布局設(shè)計過程會越少。

根據(jù)以上設(shè)計原則坯认,我們就實現(xiàn)了帖子詳情部分的布局設(shè)計翻擒。具體代碼實現(xiàn)在 github 源碼中的 pages/article_detail/index.dart 中。接下來我將用上面的原則來設(shè)計我們 Two You Friend App 的“客人態(tài)主頁”頁面鹃操。

實踐應(yīng)用

我們先來看下我們需要實現(xiàn)的效果韭寸,如圖 2 所示。

圖 2 客人態(tài)頁面

根據(jù)圖 2 的界面我們還是先繪制一個組件樹荆隘,如圖 3 所示恩伺。

圖 3 客人態(tài)組件樹設(shè)計

接下來,我們在圖 3 的基礎(chǔ)上椰拒,應(yīng)用布局設(shè)計的 8 個過程晶渠,一步步來優(yōu)化這個組件樹。

豎和橫

豎著來看四個組件分別為 guest 的 Column 子組件燃观,因此需要標記為 Column褒脯。然后再橫著看每個子組件:

guest_header,包含兩部分左邊為 user_info 組件(其中又包含 Image 和 Text)缆毁,右邊為 Icon 組件番川;

Divider,是一條分割線脊框;

guest_bar颁督,包含了三個并列的組件,分別是 Icon浇雹、Icon 和 Text沉御;

content_list,這個應(yīng)用 article_card 子組件即可昭灵,該組件已經(jīng)在前面介紹過具體設(shè)計吠裆。

分析完后伐谈,我們將會得到圖 4 組件樹。

圖 4 組件樹+布局設(shè)計

從圖 4 我們可以看到试疙,在組件與組件之間增加了布局組件的應(yīng)用 Column 诵棵、Row 和 Expanded。

高和寬

上面組件中效斑,有兩個組件是需要設(shè)置的非春,一個是 Divider ,一個是 content_list 缓屠。后者需要設(shè)置的目的是,因為列表組件超出會引起布局異常护侮。因此 content_list 是需要使用 Expanded 來包裹敌完,這部分可以不體現(xiàn)在界面中。

上和下

由于圖 2 這里就沒有需要設(shè)置上下的間隔羊初,因此組件圖也不需要修改滨溉。這里主要看每個 Column 組件下的子節(jié)點。

左和右

根據(jù)這個規(guī)則长赞,我們看下每個 Row 組件下的子節(jié)點之間是否需要設(shè)置 Padding 晦攒。根據(jù) UI 稿分析,我們可以了解到 user_info 和 guest_bar 組件的子組件都需要設(shè)置左右填充得哆,因此在圖 2 基礎(chǔ)上脯颜,我們增加 Padding 布局設(shè)計,并重新繪制組件圖贩据,可以最終得到圖 5 的一個組件+布局的設(shè)計結(jié)果栋操。

圖 5 組件樹+布局設(shè)計結(jié)果

在將組件樹和布局設(shè)計完成后,我們再去進行組件的代碼編寫饱亮,這部分代碼大家可以前往 github 的源碼的 pages/user_page/guest.dart 文件中查看矾芙,具體的代碼比較相似,這里就不過多介紹了近上。

總結(jié)

本課時介紹了幾個常用的布局組件和布局設(shè)計的思想(8 個過程)剔宪,最后通過實現(xiàn)“客人態(tài)主頁“來實踐組件樹+布局的設(shè)計思想。相關(guān)頁面的知識點就介紹完了壹无,接下來我會在源碼中更新其他界面內(nèi)容葱绒,對于比較核心的一些知識點我們還會在 18 課時中介紹,其他重復(fù)知識點格遭,就不再介紹了哈街。

下一課時我們將帶著現(xiàn)有的 Two You Friend App 代碼,教大家如何打包 Android 和 iOS 發(fā)布包拒迅。

轉(zhuǎn)自:https://kaiwu.lagou.com/course/courseInfo.htm?courseId=251#/detail/pc?id=3533

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末骚秦,一起剝皮案震驚了整個濱河市她倘,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌作箍,老刑警劉巖硬梁,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異胞得,居然都是意外死亡荧止,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進店門阶剑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來跃巡,“玉大人,你說我怎么就攤上這事牧愁∷匦埃” “怎么了?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵猪半,是天一觀的道長兔朦。 經(jīng)常有香客問我,道長磨确,這世上最難降的妖魔是什么沽甥? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮乏奥,結(jié)果婚禮上摆舟,老公的妹妹穿的比我還像新娘。我一直安慰自己英融,他們只是感情好盏檐,可當(dāng)我...
    茶點故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著驶悟,像睡著了一般胡野。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上痕鳍,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天硫豆,我揣著相機與錄音,去河邊找鬼笼呆。 笑死熊响,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的诗赌。 我是一名探鬼主播汗茄,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼铭若!你這毒婦竟也來了洪碳?” 一聲冷哼從身側(cè)響起递览,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎瞳腌,沒想到半個月后绞铃,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡嫂侍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年儿捧,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片挑宠。...
    茶點故事閱讀 40,102評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡菲盾,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出各淀,到底是詐尸還是另有隱情亿汞,我是刑警寧澤,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布揪阿,位于F島的核電站,受9級特大地震影響咆畏,放射性物質(zhì)發(fā)生泄漏南捂。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一旧找、第九天 我趴在偏房一處隱蔽的房頂上張望溺健。 院中可真熱鬧,春花似錦钮蛛、人聲如沸鞭缭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽岭辣。三九已至,卻和暖如春甸饱,著一層夾襖步出監(jiān)牢的瞬間沦童,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工叹话, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留偷遗,地道東北人。 一個月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓驼壶,卻偏偏與公主長得像氏豌,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子热凹,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,044評論 2 355