歡迎關注『郝先生談技術』頭條號,您的關注,是對作者最大的鼓勵,也是作者創作的動力。
之前的文章中有朋友評論說不知道Flutter是什麼,那麼正式開始文章之前,先簡單介紹下Flutter。Flutter是Google公司開源的一套移動平臺應用開發的框架,在2018年世界移動大會上與廣大開發者正式見面,它實現了編寫一套代碼,iOS/Android多平臺運行願景。使用全新的架構方案,應用程序直接轉義為原生底層代碼,而非Javascript解釋模式,更加高效,並且提供Hot Reload功能,方便開發者快速查看頁面效果。Flutter官網及社區為Web、iOS、Android開發者提供了非常友好的技術文檔,同時Dart語言吸納了眾多面向對象語言的優良特性,簡單易用,對於Java、Objective-C、swift面嚮對象語言使用者而言,可以很快適應Dart語言。豐富的第三方組件庫,可以讓開發者方便快速的開發應用。另外,儘管我們有了開發應用的捷徑,但是仍然需要我們對蘋果/安卓原生環境和應用簽名打包機制有所瞭解,因此如果你有一定的蘋果/安卓原生基礎,或者曾經是一名iOS/Android開發者,那就再好不過了。
由於是一個系列教程,因此如果沒有看過之前文章的朋友,請先查看
這篇文章我們將完成行星的卡片信息展示部分,顯示行星的名稱、位置、距離和重力等信息,加黑字體代表新增代碼 。完成後的效果如下圖所示。
第一步 創建數據模型
① 在lib文件夾下,新建Planet.dart
② 在Planet.dart裡,添加屬性、構造函數
class Planet {
final int id;
final String name;
final String location;
final String distance;
final String gravity;
final String description;
final String image;
const Planet({ this.id, this.name, this.location, this.distance, this.gravity, this.description, this.image });
}
第二步 添加自定義字體
① 將字體-Poppins-Regular.ttf,放到assets -> fonts文件夾下。
如果沒有該字體,請到這裡下載:
[email protected]:hao2008/flutter-demo.git
② 在pubspect.yaml裡添加字體
fonts:
- family: Poppins
fonts:
- asset: assets/fonts/Poppins-SemiBold.ttf
weight: 600
- asset: assets/fonts/Poppins-Regular.ttf
weight: 400
第三步 創建字體樣式
說明:copyWith()可以使用或覆蓋被複制者的樣式,color和foreground不能同時使用。
① 在PlanetRow.dart裡,添加基礎樣式。可以添加到import的下一行。
final baseTextStyle = const TextStyle(fontFamily: 'Poppins');
② 添加標題樣式,基於基礎樣式
final headerTextStyle = baseTextStyle.copyWith(
color: Colors.white, fontSize: 18.0, fontWeight: FontWeight.w600);
③ 添加內容樣式,基於基礎樣式
final regularTextStyle = baseTextStyle.copyWith(
color: const Color(0xffb6b2df), fontSize: 9.0, fontWeight: FontWeight.w400);
④ 添加副標題樣式,基於內容樣式
final subHeaderTextStyle = regularTextStyle.copyWith(fontSize: 12.0);
第四步 在PlanetRow.dart裡,添加屬性、構造方法
class PlanetRow extends StatelessWidget {
final Planet planet;
PlanetRow(this.planet);
}
第五步 添加私有方法:創建圖標+數值的小部件
Widget _planetValue({String value, String image}) {
return new Row(
children:
// 圖標
new Image.asset(
image,
height: 12.0,
),
// 間距8.0
new Container(
width: 8.0,
),
// 數值
new Text(
value,
style: regularTextStyle,
),], );}
第六步 在PlanetRow.dart裡,添加planetCardContent部件,設置文字內容、樣式等
final planetCardContent = new Container(
margin: new EdgeInsets.fromLTRB(76.0, 16.0, 16.0, 16.0),
// 鋪滿
constraints: new BoxConstraints.expand(),
child: new Column(
// 水平方向,自視圖左對齊
crossAxisAlignment: CrossAxisAlignment.start,
children:
// 間距4.0
new Container(
height: 4.0,
),
// 行星名稱
new Text(
planet.name,
style: headerTextStyle,
),
// 間距10.0
new Container(
height: 10.0,
),
// 行星位置
new Text(
planet.location,
style: subHeaderTextStyle,
),
// 橫崗
new Container(
// 上下間距8.0
margin: new EdgeInsets.symmetric(vertical: 8.0),
height: 2.0,
width: 18.0,
color: new Color(0xff00c6ff),
),
// 距離和重力
new Row(
// Expanded Widget:Row/Column/Flex子控件鋪滿主軸方向
children:
new Expanded(
child: _planetValue(
value: planet.distance,
image: 'assets/img/ic_distance.png')),
new Expanded(
child: _planetValue(
value: planet.gravity,
image: 'assets/img/ic_gravity.png'))
],)],),);
第七步 修改planetThumbnail部件,從planet模型獲取圖片
final planetThumbnail = new Container(
child: new Image(
// 使用AssetImage Widget加載圖片
image: new AssetImage(planet.image),
height: 92.0,
width: 92.0,
),
);
第八步 修改planetCart部件,添加planetCartContent部件
final planetCard = new Container(
child: planetCardContent,
);
第九步 planetRow.dart完整代碼如下
import 'package:flutter/material.dart';
import 'package:demo/Planet.dart';
// 基礎樣式
final baseTextStyle = const TextStyle(fontFamily: 'Poppins');
// 標題樣式,基於基礎樣式
final headerTextStyle = baseTextStyle.copyWith(
color: Colors.white, fontSize: 18.0, fontWeight: FontWeight.w600);
// 內容樣式,基於基礎樣式
final regularTextStyle = baseTextStyle.copyWith(
color: const Color(0xffb6b2df), fontSize: 9.0, fontWeight: FontWeight.w400);
// 副標題樣式,基於內容樣式
final subHeaderTextStyle = regularTextStyle.copyWith(fontSize: 12.0);
class PlanetRow extends StatelessWidget {
final Planet planet;
PlanetRow(this.planet);
// ① 下劃線代表私有方法
// ② 生成圖標、數值的部件
Widget _planetValue({String value, String image}) {
return new Row(
children:
// 圖標
new Image.asset(
image,
height: 12.0,
),
// 間距8.0
new Container(
width: 8.0,
),
// 數值
new Text(
value,
style: regularTextStyle,
),
],
);
}
@override
Widget build(BuildContext context) {
final planetCardContent = new Container(
margin: new EdgeInsets.fromLTRB(76.0, 16.0, 16.0, 16.0),
// 鋪滿
constraints: new BoxConstraints.expand(),
child: new Column(
// 水平方向,自視圖左對齊
crossAxisAlignment: CrossAxisAlignment.start,
children:
// 間距4.0
new Container(
height: 4.0,
),
// 行星名稱
new Text(
planet.name,
style: headerTextStyle,
),
// 間距10.0
new Container(
height: 10.0,
),
// 行星位置
new Text(
planet.location,
style: subHeaderTextStyle,
),
// 橫崗
new Container(
// 上下間距8.0
margin: new EdgeInsets.symmetric(vertical: 8.0),
height: 2.0,
width: 18.0,
color: new Color(0xff00c6ff),
),
// 距離和重力
new Row(
// Expanded Widget:Row/Column/Flex子控件鋪滿主軸方向
children:
new Expanded(
child: _planetValue(
value: planet.distance,
image: 'assets/img/ic_distance.png')),
new Expanded(
child: _planetValue(
value: planet.gravity,
image: 'assets/img/ic_gravity.png'))
],)],),);
final planetThumbnail = new Container(
// 上下向內偏移16.0
margin: new EdgeInsets.symmetric(vertical: 16.0),
// 水平方向靠左邊線,垂直方向居中,等價於FractionalOffset(0.0, 0.5);
alignment: FractionalOffset.centerLeft,
child: new Image(
// 使用AssetImage Widget加載圖片
image: new AssetImage(planet.image),
height: 92.0,
width: 92.0,
),
);
final planetCard = new Container(
height: 124.0,
// 左側偏移46.0
margin: new EdgeInsets.only(left: 46.0),
// 設置樣式
decoration: new BoxDecoration(
color: new Color(0xff333366),
// 設置為矩形
shape: BoxShape.rectangle,
// 設置圓角為8.0
borderRadius: new BorderRadius.circular(8.0),
// 設置陰影,向下偏移10.0,模糊半徑10.0
boxShadow: [
new BoxShadow(
color: Colors.black12,
// 模糊半徑10.0
blurRadius: 10.0,
// 向下偏移10.0
offset: new Offset(0.0, 10.0),
)
]),
child: planetCardContent,
);
return new Container(
height: 120.0,
// EdgeInsets.symmetric等同於EdgeInsets.only(top: 16.0, bottom: 16.0, left: 24.0, right: 24.0)
margin: const EdgeInsets.symmetric(
// 上下偏移16.0
vertical: 16.0,
// 左右偏移24.0
horizontal: 24.0,
),
// Stack Widget用於創建上下重疊部件
child: new Stack(
children:
), ); }}
第十步 在HomePageBody.dart裡,添加一組數據,並修改build函數
import 'package:flutter/material.dart';
import 'package:demo/PlanetRow.dart';
import 'package:demo/Planet.dart';
class HomePageBody extends StatelessWidget {
List
const Planet(
id: 1,
name: "火星",
location: "銀河系",
distance: "220.0m km",
gravity: "3.7 m/s",
description: "遙遠的星球",
image: "assets/img/mars.png",
),
const Planet(
id: 1,
name: "海王星",
location: "銀河系",
distance: "54.6m km",
gravity: "11.15 m/s",
description: "遙遠的星球",
image: "assets/img/neptune.png",
),
const Planet(
id: 1,
name: "月球",
location: "銀河系",
distance: "54.6m km",
gravity: "1.622 m/s",
description: "遙遠的星球",
image: "assets/img/moon.png",
),
const Planet(
id: 1,
name: "地球",
location: "銀河系",
distance: "0m km",
gravity: "9.8 m/s",
description: "我們的星球",
image: "assets/img/earth.png",
),
const Planet(
id: 1,
name: "水星",
location: "銀河系",
distance: "54.6m km",
gravity: "3.7 m/s",
description: "遙遠的星球",
image: "assets/img/mercury.png",
),
];
@override
Widget build(BuildContext context) {
return new PlanetRow(planets[0]);
}
}
第十一步 運行Flutter項目,iPhone8模擬器效果如下:
第十二步 結束
項目地址:
[email protected]:hao2008/flutter-demo.git
下篇預告:行星之卡片列表
歡迎關注『郝先生談技術』頭條號,您的關注,是對作者最大的鼓勵,也是作者創作的動力。
閱讀更多 郝先生談技術 的文章