相對(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)站設(shè)計(jì)制作、網(wǎng)站建設(shè)、臺(tái)山網(wǎng)絡(luò)推廣、小程序開發(fā)、臺(tái)山網(wǎng)絡(luò)營(yíng)銷、臺(tái)山企業(yè)策劃、臺(tái)山品牌公關(guān)、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運(yùn)營(yíng)等,從售前售中售后,我們都將竭誠(chéng)為您服務(wù),您的肯定,是我們最大的嘉獎(jiǎng);創(chuàng)新互聯(lián)公司為所有大學(xué)生創(chuàng)業(yè)者提供臺(tái)山建站搭建服務(wù),24小時(shí)服務(wù)熱線:028-86922220,官方網(wǎng)址:chinadenli.net
根據(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中自定義組件一般有兩種方式:
CustomPaint繼承自SingleChildRenderObjectWidget,即它可以在通過(guò)嵌套引入到widget樹中,并且可以有一個(gè)child子widget。它的構(gòu)造方法如下:
painter和foregroundPainter需要接收CustomPainter對(duì)象,是CustomPaint核心。CustomPainter是進(jìn)行UI繪制的核心類,繪制時(shí), CustomPaint 首先在畫布上調(diào)用 painter繪制 , 然后再繪制它的 child Widget, child 繪制完成后再調(diào)用 foregroundPainter 進(jìn)行繪制。
size屬性標(biāo)識(shí)繪制區(qū)域大小,但當(dāng)CustomPaint有child,該屬性將會(huì)忽略,而使用child的大小為繪制區(qū)域大小。
isComplex和willChange用于控制繪制層緩存處理的,這里暫不討論。
可實(shí)現(xiàn)CustomPainter子類進(jìn)行UI繪制
實(shí)現(xiàn)paint方法進(jìn)行真正的繪制,canvas是畫布對(duì)象,size是繪制區(qū)域,是從CustomPaint中size屬性傳遞得到的。繪制過(guò)程與Android原生開發(fā)十分類似,連API都十分相像,這點(diǎn)對(duì)熟悉Android原生開發(fā)者真是太友好了。
Paint對(duì)象是畫筆對(duì)象,就是繪圖工具,我們可以設(shè)置畫筆的顏色、粗細(xì)、是否抗鋸齒、筆觸形狀以及作畫風(fēng)格等,通過(guò)這些屬性我們可以很方便的來(lái)定制自己的UI效果,在繪制的過(guò)程中可以定義多個(gè)畫筆,以便實(shí)現(xiàn)多種風(fēng)格圖形的集合。
根據(jù)需求選擇合適的畫筆屬性,完成你的繪制。
Canvas是繪制的畫布,它包含了很多繪制方法,可以繪制出各種形狀的圖形。需要注意的是,畫布是應(yīng)用所有控件都在使用的, 所以通過(guò)這個(gè)畫布其實(shí)是可以繪制充滿屏幕的內(nèi)容的,每次繪制都應(yīng)該限制在本控件的區(qū)域(Size)內(nèi), 以免繪制覆蓋到其他組件。
下面介紹下Canvas的繪制方法:
PointMode是個(gè)枚舉
p1、p2為線段兩個(gè)端點(diǎn)
Rect定義矩形的大小位置,有多種構(gòu)造方式:
RRect描述圓角矩形,他通過(guò)Rect和Radius來(lái)構(gòu)造
畫圓比較簡(jiǎn)單,c表示圓心位置,radius是半徑。
橢圓使用外接矩形確定大小位置,rect就是外接矩形。
繪制弧形,先確定弧形對(duì)應(yīng)的橢圓,同樣地用外接矩形rect確定橢圓,然后根據(jù)起始點(diǎn)和結(jié)束點(diǎn)角度來(lái)確定那一段弧度,startAngle,sweepAngle分別代表起始和結(jié)束點(diǎn)角度,角度用弧度表示法。
useCenter表示是否連接閉合形狀,userCenter = false表示不閉合,即畫一段弧線,userCenter = true表示閉合,即繪制一個(gè)扇形。
繪制路徑,關(guān)鍵在于構(gòu)建路徑Path,可以直接new Path對(duì)象,然后通過(guò)path方法可以連接出圖形,path關(guān)鍵方法如下:
還有其他方法,有興趣可以查看API。
ClipRect控件默認(rèn)是通過(guò)限制子widget的繪制區(qū)域來(lái)達(dá)到裁剪的效果的,通過(guò)custom clipper,可以自定義裁剪的大小跟坐標(biāo)
ClipRect的定義如下
ClipRect class默認(rèn)是沒有任何裁剪效果的,需要通過(guò)clipper參數(shù)告訴ClipRect如何去裁剪,clipper是個(gè)CustomClipper類型,CustomClipper是個(gè)抽象接口類,我們通過(guò)繼承CustomClipper,重寫 getClip 方法可以定義一個(gè)裁剪區(qū)域,通過(guò)重寫 shouldReclip 方法來(lái)告訴ClipRect當(dāng)一個(gè)新的clipper被設(shè)置了是否需要更新裁剪區(qū)域,譬如開始設(shè)置的clipper裁剪坐標(biāo)是從(10,10)開始的,新設(shè)置的clipper裁剪坐標(biāo)是(20,20),那么shouldReclip需要返回true來(lái)通知ClipRect更新裁剪區(qū)域。
下面這個(gè)例子從網(wǎng)絡(luò)上加載一張圖片,并且進(jìn)行裁剪,裁剪坐標(biāo)是(10,10) 裁剪的寬高是圖片的寬高減去10
效果如下
對(duì)于一些復(fù)雜或不規(guī)則的UI,我們可能無(wú)法使用現(xiàn)有的 Widget 組合去實(shí)現(xiàn),比如需要一個(gè)帶動(dòng)畫的進(jìn)度條,
又或者是一個(gè)特殊形狀的多邊形等等,當(dāng)然有時(shí)候我們可以直接用圖片去實(shí)現(xiàn),但是并沒有達(dá)到我們想要
的效果,反而會(huì)讓我們產(chǎn)生不良的體驗(yàn)。
幾乎所有的UI系統(tǒng)都會(huì)提供一個(gè)自繪UI的接口,這個(gè)接口通常會(huì)提供一塊2D畫布Canvas,Canvas內(nèi)部封裝了
一些基本繪制的API,開發(fā)者可以通過(guò)Canvas繪制各種自定義圖形。在Flutter中,提供了一個(gè)CustomPaint Widget,
它可以結(jié)合一個(gè)畫筆CustomPainter來(lái)實(shí)現(xiàn)繪制自定義圖形。
我們看看 CustomPaint 構(gòu)造函數(shù):
1.painter: 背景畫筆,會(huì)顯示在子節(jié)點(diǎn)后面;
2.foregroundPainter: 前景畫筆,會(huì)顯示在子節(jié)點(diǎn)前面
3.size:當(dāng)child為null時(shí),代表默認(rèn)繪制區(qū)域大小,如果有child則忽略此參數(shù),畫布尺寸則為child尺寸。如果有child但是想指定畫布為特定大小,可以使用SizeBox包裹CustomPaint實(shí)現(xiàn)。
4.isComplex:是否復(fù)雜的繪制,如果是,F(xiàn)lutter會(huì)應(yīng)用一些緩存策略來(lái)減少重復(fù)渲染的開銷。
5.willChange:和isComplex配合使用,當(dāng)啟用緩存時(shí),該屬性代表在下一幀中繪制是否會(huì)改變。
可以看到,繪制時(shí)我們需要提供前景或者背景畫筆,兩者也可以同時(shí)提供,
我們的畫筆需要繼承 CustomPainter 類,我們?cè)诋嫻P類中實(shí)現(xiàn)真正的繪制邏輯。
顧名思義畫布的意思,我們繪制布局當(dāng)然是在一張畫布上進(jìn)行繪制,畫布為我們繪制圖形提供了很多方法。(熟悉畫布的就無(wú)需再看了)
在繪制之前我們需要準(zhǔn)備畫筆 Paint,就如畫畫一樣,你用什么筆就能畫什么樣的畫,在Paint中,
我們可以配置畫筆的各種屬性如粗細(xì)、顏色、樣式等。如:
好了,繼承CustomPainter類,然后準(zhǔn)備好畫筆,就可以在畫布上盡情的揮灑了!
寫的挺簡(jiǎn)單的,就是介紹了一下自定義view的準(zhǔn)備工作以及畫布畫筆的功能,具體實(shí)戰(zhàn)請(qǐng)看下一篇博客。
文章題目:flutter繪制區(qū)域,flutter畫布
網(wǎng)頁(yè)路徑:http://chinadenli.net/article47/dsechej.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供自適應(yīng)網(wǎng)站、定制開發(fā)、、營(yíng)銷型網(wǎng)站建設(shè)、虛擬主機(jī)、網(wǎng)站維護(hù)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)