相對(duì)于iOS開發(fā),F(xiàn)lutter的布局更具有靈活性,每個(gè)頁(yè)面設(shè)計(jì)都不一樣,相同頁(yè)面可選擇的布局方式也不一樣,如果單純的說(shuō)應(yīng)該如何去布局,我覺得不現(xiàn)實(shí),大家可以參考下 Flutter官方的布局教程 。接下來(lái),筆者,通過(guò)項(xiàng)目中的一個(gè)頁(yè)面,來(lái)一步一步的拆解布局的流程。整個(gè)過(guò)程,基本上按照拆解、組件封裝、具體布局這三步來(lái)的。
創(chuàng)新互聯(lián)建站專注為客戶提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于網(wǎng)站制作、網(wǎng)站設(shè)計(jì)、睢縣網(wǎng)絡(luò)推廣、小程序定制開發(fā)、睢縣網(wǎng)絡(luò)營(yíng)銷、睢縣企業(yè)策劃、睢縣品牌公關(guān)、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運(yùn)營(yíng)等,從售前售中售后,我們都將竭誠(chéng)為您服務(wù),您的肯定,是我們最大的嘉獎(jiǎng);創(chuàng)新互聯(lián)建站為所有大學(xué)生創(chuàng)業(yè)者提供睢縣建站搭建服務(wù),24小時(shí)服務(wù)熱線:18982081108,官方網(wǎng)址:www.cdcxhl.com
根據(jù)設(shè)計(jì)圖,可以看出整體可以分成兩部分,上面一部分是系統(tǒng)介紹模塊,下面一部分是真正的登錄內(nèi)容,因?yàn)樯婕暗蒋B加,因此考慮用Stack;
系統(tǒng)介紹模塊部分:整體也是涉及到疊加,考慮用Stack,分為四部分。最底部漸變色背景用一個(gè)contanier,無(wú)須指定位置,全視圖擴(kuò)展;載放logo圖標(biāo)在上一層,用Image。最后兩個(gè)Text同級(jí)放在最上層。Image,Text各用Positioned包裹去指定位置。
登錄內(nèi)容模塊是最外層是一個(gè)Contanier容器,去控制背景色和圓角。然后是一個(gè)Column元素,逐行排列。
第一行為Image,
第二行為Text,
第三行可以看成一個(gè)小Column,分兩塊進(jìn)行布局
第四行可以看成一個(gè)小Column,分兩塊進(jìn)行布局
第五行可以看作一個(gè)TextButton,
第六行可以看作一個(gè)Row,分三塊進(jìn)行布局
通過(guò)上面這樣一步一步的分析后,基本上對(duì)大致的布局有了一個(gè)了解,最外層的控件大致選對(duì)(只要能實(shí)現(xiàn)的話,就是復(fù)雜度以及效率的問(wèn)題),然后一步一步的拆解每一行的元素,如果有重復(fù)的或者覺得可以封裝出來(lái)的部分,則進(jìn)行下一步。
每一行的拆解,大致也是按照這個(gè)思路來(lái)進(jìn)行,因此筆者在這里就不做講解了。
在做到第三第四行的時(shí)候,發(fā)現(xiàn)這兩個(gè)很相似,而且設(shè)計(jì)到一些交互邏輯,筆者就想對(duì)第三第四行的這種展示進(jìn)行封裝,覺得今后的布局可能會(huì)用到,因此在這一步,可以先把這一塊兒抽離出一個(gè)控件。利用TextField來(lái)實(shí)現(xiàn)這種輸入操作,具體的實(shí)現(xiàn)筆者不再詳細(xì)的描述了。
經(jīng)過(guò)這一步,整體的規(guī)劃設(shè)計(jì)圖已經(jīng)有了,各個(gè)組件也都有了,接下來(lái)的工作就是組裝了。
具體布局設(shè)計(jì)到一些細(xì)節(jié)的地方,例如整體Column的居中對(duì)齊(crossAxisAlignment)、間隔(Padding或Container包裹,筆者更喜歡用SizedBox占位)、居左居右居中(Align)、點(diǎn)擊事件(GestureDetector)以及圓角(BorderRadius)等一些特殊情況。
像第六行row是放在底部的,就可以在第六行前面增加一個(gè)Spacer()去填充空白區(qū)域。
對(duì)文字顏色大小等,可以用TextStyle直接設(shè)置。
對(duì)于輸入框的刪除按鈕,可以用Offstage這種Flutter特有的控制顯示隱藏的控件。
flutter布局需要先了解flutter所有布局的widget,首先f(wàn)lutter布局分為Container、RenderObjectWidget和ParentDataWidget。而RenderObject中經(jīng)常使用的有SingleChildRenderObjectWidget(單節(jié)點(diǎn))和MultiChildRenderObjectWidget(多節(jié)點(diǎn))。
flutter中基礎(chǔ)的widget,可以為子節(jié)點(diǎn)設(shè)置內(nèi)間距。當(dāng)padding沒(méi)有child的時(shí)候,它會(huì)產(chǎn)生一個(gè)寬為left+right,高為top+bottom的區(qū)域,當(dāng)padding的child不為空的時(shí)候會(huì)將約束傳遞給child。一般在使用間距的地方使用。
設(shè)置child的對(duì)齊方式,并根據(jù)child的尺寸調(diào)整自身的尺寸。
設(shè)置透明度
用于矩形圓角裁剪組件
用于圓形裁剪,但是可以添加陰影和Z軸
給組件繪制區(qū)域大小
百分比布局,可以通過(guò)widthFactor或者h(yuǎn)eightFactor設(shè)置寬高占比
子組件疊加布局,也稱絕對(duì)布局
mainAxisAlignment: start:頂頭 center:居中 end:接尾 spaceAround:中間的孩子均分,兩頭的孩子空一半 spaceBetween:頂頭接尾其他均分 spaceEvenly:均勻分布
crossAxisAlignment: start:頂頭 center:居中 end:接尾 stretch:伸展
mainAxisSize: max:父容器沒(méi)有約束的話,column自身會(huì)盡可能延伸 min:不會(huì)延伸,只會(huì)包裹自己
屬性和column屬性一致,只是方向不同,一個(gè)豎直方向一個(gè)水平方向。使用方法也類似。
Wrap可以實(shí)現(xiàn)流布局,單行的Wrap跟Row一樣,單列的Wrap則跟Colum一樣.但是Row和Column都是單行單列的,Wrap可以多行多列。
Wrap能做的事情,flow也能做。但是flow會(huì)比較復(fù)雜點(diǎn)。flow類似于OC中CollectionLayout,需要自己實(shí)現(xiàn)子組件的位置以及大小。但是flow的性能比較好,靈活。
自定義FlowDelegate
運(yùn)行結(jié)果:
絕對(duì)定位布局,用于指定組件的具體位置
Expanded組件可以使row、column或者flex子組件在其主軸上展開并填充可用空間。如果多個(gè)組件展開的話,會(huì)按照比例分割。
Tip:Expanded組件要在row、column或者flex的子組件中使用。具有兩個(gè)屬性,child:子組件,flex:所占比例
對(duì)于初學(xué)flutter的朋友來(lái)說(shuō),要知道,flutter的UI萬(wàn)物皆Widget。
flutter所寫的頁(yè)面的結(jié)構(gòu)可以被看成套娃,一層套一層,一層套一層,一層套一層。。。。。。
Flutter Widget采用現(xiàn)代響應(yīng)式框架構(gòu)建,這是從 React 中獲得的靈感,中心思想是用widget構(gòu)建你的UI。 Widget描述了他們的視圖在給定其當(dāng)前配置和狀態(tài)時(shí)應(yīng)該看起來(lái)像什么。當(dāng)widget的狀態(tài)發(fā)生變化時(shí),widget會(huì)重新構(gòu)建UI,F(xiàn)lutter會(huì)對(duì)比前后變化的不同, 以確定底層渲染樹從一個(gè)狀態(tài)轉(zhuǎn)換到下一個(gè)狀態(tài)所需的最小更改。
Text : 該 widget 可讓創(chuàng)建一個(gè)帶格式的文本。
Row 、 Column : 這些具有彈性空間的布局類Widget可讓您在水平( Row )和垂直( Column )方向上創(chuàng)建靈活的布局。
Stack :取代線性布局 (和Android中的LinearLayout相似),Stack允許子 widget 堆疊, 你可以使用 Positioned 來(lái)定位他們相對(duì)于 Stack 的上下左右四條邊的位置。
Container : Container 可讓您創(chuàng)建矩形視覺元素。 您可以為 Container 裝飾一個(gè) BoxDecoration , 如 background、一個(gè)邊框、或者一個(gè)陰影。 Container 也可以具有邊距(margins)、填充(padding)和應(yīng)用于其大小的約束(constraints)。另外, Container 可以使用矩陣在三維空間中對(duì)其進(jìn)行變換。
具體的演示見我另外的博客
有一部分Widget都有一個(gè) child 屬性,用于容納唯一的子Widget。
例如:Container、Center、Padding、Align等Widget。
還有一部分Widget允許存在多個(gè)子Widget,用 children 作為屬性。
例如:Row、Column、Stack等Widget。
在StatefulWidget調(diào)用createState之后,框架將新的狀態(tài)插入樹種,然后調(diào)用狀態(tài)對(duì)象的initState。子類化State可以重寫initState,以完成僅需要一次執(zhí)行的工作。當(dāng)然在initState的實(shí)現(xiàn)中需要調(diào)用super.initState
當(dāng)一個(gè)狀態(tài)對(duì)象不再需要時(shí),框架調(diào)用狀態(tài)對(duì)象的dispose。也可以通過(guò)覆蓋dispose方法來(lái)執(zhí)行清理工作。
OVER~
學(xué)習(xí)Row和Column之前,我們先學(xué)習(xí)主軸和交叉軸的概念 。
Row組件用于將所有的子Widget排成一行。
MainAxisAlignment: start、end、center、spaceBetween、spaceAround、spaceEvenly
CrossAxisAlignment: 、start、end、center、baseline、stretch
Row 的 MainAxisAlignment各個(gè)屬性效果如下圖所示:
Column 的 MainAxisAlignment各個(gè)屬性效果如下圖所示:
Flutter中不太推薦控件的疊加,但是在實(shí)際項(xiàng)目開發(fā)中,我們很有可能需要重疊顯示,比如在一張圖片上顯示文字或者一個(gè)按鈕等。這種需求很常見。所以在Flutter中提供Stack來(lái)實(shí)現(xiàn)層疊布局。
效果如下圖所示:
【Tips:】 Positioned組件一般配合Stack組件使用。
Flex布局的學(xué)習(xí)記錄在這里,方便自己日后查閱。
所謂線性布局,即指沿水平或垂直方向排列子組件。Flutter 中通過(guò)Row和Column來(lái)實(shí)現(xiàn)線性布局,類似于Android 中的LinearLayout控件。Row和Column都繼承自Flex,我們將在彈性布局一節(jié)中詳細(xì)介紹Flex
對(duì)于線性布局,有主軸和縱軸之分,如果布局是沿水平方向,那么主軸就是指水平方向,而縱軸即垂直方向;如果布局沿垂直方向,那么主軸就是指垂直方向,而縱軸就是水平方向。在線性布局中,有兩個(gè)定義對(duì)齊方式的枚舉類MainAxisAlignment和CrossAxisAlignment,分別代表主軸對(duì)齊和縱軸對(duì)齊。
Row可以沿水平方向排列其子widget。定義如下:
解釋:第一個(gè)Row很簡(jiǎn)單,默認(rèn)為居中對(duì)齊;第二個(gè)Row,由于mainAxisSize值為MainAxisSize.min,Row的寬度等于兩個(gè)Text的寬度和,所以對(duì)齊是無(wú)意義的,所以會(huì)從左往右顯示;第三個(gè)Row設(shè)置textDirection值為TextDirection.rtl,所以子組件會(huì)從右向左的順序排列,而此時(shí)MainAxisAlignment.end表示左對(duì)齊,所以最終顯示結(jié)果就是圖中第三行的樣子;第四個(gè) Row 測(cè)試的是縱軸的對(duì)齊方式,由于兩個(gè)子 Text 字體不一樣,所以其高度也不同,我們指定了verticalDirection值為VerticalDirection.up,即從低向頂排列,而此時(shí)crossAxisAlignment值為CrossAxisAlignment.start表示底對(duì)齊
Column可以在垂直方向排列其子組件。參數(shù)和Row一樣,不同的是布局方向?yàn)榇怪保鬏S縱軸正好相反,讀者可類比Row來(lái)理解,下面看一個(gè)例子:
解釋:
實(shí)際上,Row和Column都只會(huì)在主軸方向占用盡可能大的空間,而縱軸的長(zhǎng)度則取決于他們最大子元素的長(zhǎng)度 。如果我們想讓本例中的兩個(gè)文本控件在整個(gè)手機(jī)屏幕中間對(duì)齊,我們有兩種方法:
如果Row里面嵌套R(shí)ow,或者Column里面再嵌套Column,那么只有最外面的Row或Column會(huì)占用盡可能大的空間,里面Row或Column所占用的空間為實(shí)際大小,下面以Column為例說(shuō)明:
如果要讓里面的Column占滿外部Column,可以使用Expanded 組件:
表格布局和線性布局比較相似,只是使用起來(lái)更簡(jiǎn)潔一些。
本地Flutter 2.10.1,Mac版Android Studio Bumblebee | 2021.1.1 Patch 2
我是小栗子,初學(xué)Flutter ,文章會(huì)根據(jù)學(xué)習(xí)進(jìn)度不定時(shí)更新,請(qǐng)多多指教~~