1. 程式人生 > >Flutter 開發從 0 到 1(三)佈局與 ListView

Flutter 開發從 0 到 1(三)佈局與 ListView

![](http://pic1.win4000.com/wallpaper/2020-05-14/5ebd04a4a3e1c.jpg) 上週日出去玩了,因此沒時間寫文章。我司加班到 11 點,第二天可以晚上班一個小時,加班到 12 點,可以晚上班兩個小時,以此類推,為什麼說這個,對的,加班第二天我沒有多睡覺,而是起來抓緊時間寫文章,好了,廢話不多說,進入今天的主題。 ## 佈局 說到 Android 佈局,不是很難,會在對應的 xml 里布局,Flutter 裡沒有 xml,都在程式碼裡寫,給人感覺就很難,看下我們要實現的佈局: ![](https://smartloong.oss-cn-shanghai.aliyuncs.com/IMG_4281.jpg) 開啟 PhotoShop,看下背景色 #ededed,日期字型顏色 #a6a6a6,標題字型顏色 #1b1b1b,摘要字型顏色 #808080。 公眾號這是列表,我先將 item 搞定。看這佈局都是線性佈局,這要在之前,分分鐘搞定,但 Flutter……好吧,Flutter 佈局可沒那麼簡單,我花了好幾個小時才做好,期間遇到了不少困難。 ![](https://smartloong.oss-cn-shanghai.aliyuncs.com/IMG_4282.png) Flutter 也有橫向 Row 佈局和豎向 Column 佈局,我本想分 1 和 2 兩個部分,最外層豎向 Column 包含 1 和 2,2 本身是 Column,包含一個 image 和兩個 text,直接使用 Column 可以完成,當我需要設定 2 裡面白色的背景色,發現 Column 根本沒有背景色屬性,於是把 2 最外層改造成 Container。 使用 Container 沒有問題,佈局也很快實現了,接下來是實現四角的圓角效果。 Container 有 decoration,可以實現圓角,我遇到了兩個問題: 1、當 shape: BoxShape.circle 時不能設定 borderRadius ,會異常 異常資訊:'shape != BoxShape.circle ||borderRadius == null': is not true. 2、使用 BoxDecoration Container 不能使用 color,會報錯: Cannot provide both a color and a decoration To provide both, use "decoration: BoxDecoration(color: color)". 以為這樣就實現了圓角,不,不會那麼順利的,發現圖片根本沒有圓角效果,這和之前 Java 實現方式不一樣,最外層都實現了圓角,對裡面的佈局(圖片)居然沒有生效,最後只好把佈局實現如下: ![](https://smartloong.oss-cn-shanghai.aliyuncs.com/IMG_4283.png) 分成 1、2、3 部分,3 還是 Container,2 和 3 圓角效果只對上下部分分別實現,完整程式碼如下: ```dart blogItem() { var date = new Padding( padding: const EdgeInsets.only( top: 20.0, left: 10.0, right: 10.0, ), child: new Text( '2020年6月28日 22:49', textAlign: TextAlign.center, style: TextStyle(color: ColorCommon.dateColor, fontSize: 18), )); var cover = new Padding( padding: const EdgeInsets.only( top: 10.0, left: 10.0, right: 10.0, ), child: new ClipRRect( borderRadius: BorderRadius.only( topLeft: Radius.circular(10.0), topRight: Radius.circular(10.0)), child: new Image.network( 'http://pic1.win4000.com/wallpaper/2020-04-21/5e9e676001e20.jpg', ))); var title = new Text( 'APP 開發從 0 到 1(一)需求與準備', style: TextStyle(color: ColorCommon.titleColor, fontSize: 22), ); var summary = new Padding( padding: const EdgeInsets.only( top: 5.0, ), child: new Text('一個人做一個專案,你也可以。', textAlign: TextAlign.left, style: TextStyle(color: ColorCommon.summaryColor, fontSize: 18))); var titleSummary = new Container( padding: const EdgeInsets.all(10.0), alignment: Alignment.topLeft, decoration: new BoxDecoration( color: Colors.white, borderRadius: BorderRadius.only( bottomLeft: Radius.circular(10.0), bottomRight: Radius.circular(10.0)), shape: BoxShape.rectangle, ), margin: const EdgeInsets.only(left: 10, right: 10.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [title, summary], ), ); var blogItem = new Column( children: [date, cover, titleSummary, date, cover, titleSummary], ); return blogItem; } ``` 實際效果如下: ![](https://smartloong.oss-cn-shanghai.aliyuncs.com/IMG_4284.png) 好了,關於 Flutter 佈局就講到這裡,我只是針對這個專案所需要的去實現,Flutter 佈局的東西還有很多,其屬性讓人眼花撩亂,可以去官網一個個去仔細學習和實踐。 ## ListView blogItem 寫好了,完成了大頭,接下來就要填充真實的資料,在《[APP 開發從 0 到 1(二)框架與網路](https://mp.weixin.qq.com/s/7XgXsQt0OKdsDZKQmEx_2A)》,有說到網路請求,其中有提到 setstate(){} 方法,呼叫這個方法會回撥 build 方法,這樣我們可以在 build 方法加個判斷,先載入 Progress,待網路資料請求完,再顯示 ListView,程式碼如下: ```dart @override Widget build(BuildContext context) { var content; if (blogList.isEmpty) { content = new Center( // 可選引數 child: child: new CircularProgressIndicator(), ); } else { content = new ListView(children: blogItem()); } return Scaffold( backgroundColor: ColorCommon.backgroundColor, appBar: AppBar( title: Text('AndBlog'), ), body: content, floatingActionButton: FloatingActionButton( tooltip: 'Increment', child: Icon(Icons.add), ), // This trailing comma makes auto-formatting nicer for build methods. ); } blogItem() { List widgets = []; for (int i = 0; i < blogList.length; i++) { Blog blog = blogList[i]; var date = new Padding( padding: const EdgeInsets.only( top: 20.0, left: 10.0, right: 10.0, ), child: new Text( // 填充真實資料 blog.date, textAlign: TextAlign.center, style: TextStyle(color: ColorCommon.dateColor, fontSize: 18), )); //…… var blogItem = new Column( children: [ date, cover, titleSummary, ], ); widgets.add(blogItem); } return widgets; } ``` 這樣 ListView 也完成了,接下來需要完成的是 ListView 載入更多。 ![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/79fe615fcee14179ba5864caa6b2a836~tplv-k3u1fbpfcp-zoom-