Flutter教程-行星之卡片信息(3)

歡迎關注『郝先生談技術』頭條號,您的關注,是對作者最大的鼓勵,也是作者創作的動力。

之前的文章中有朋友評論說不知道Flutter是什麼,那麼正式開始文章之前,先簡單介紹下Flutter。Flutter是Google公司開源的一套移動平臺應用開發的框架,在2018年世界移動大會上與廣大開發者正式見面,它實現了編寫一套代碼,iOS/Android多平臺運行願景。使用全新的架構方案,應用程序直接轉義為原生底層代碼,而非Javascript解釋模式,更加高效,並且提供Hot Reload功能,方便開發者快速查看頁面效果。Flutter官網及社區為Web、iOS、Android開發者提供了非常友好的技術文檔,同時Dart語言吸納了眾多面向對象語言的優良特性,簡單易用,對於Java、Objective-C、swift面嚮對象語言使用者而言,可以很快適應Dart語言。豐富的第三方組件庫,可以讓開發者方便快速的開發應用。另外,儘管我們有了開發應用的捷徑,但是仍然需要我們對蘋果/安卓原生環境和應用簽名打包機制有所瞭解,因此如果你有一定的蘋果/安卓原生基礎,或者曾經是一名iOS/Android開發者,那就再好不過了。

由於是一個系列教程,因此如果沒有看過之前文章的朋友,請先查看

這篇文章我們將完成行星的卡片信息展示部分,顯示行星的名稱、位置、距離和重力等信息,加黑字體代表新增代碼

。完成後的效果如下圖所示。

Flutter教程-行星之卡片信息(3)

第一步 創建數據模型

① 在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);

}


第五步 添加私有方法:創建圖標+數值的小部件

Flutter教程-行星之卡片信息(3)


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: [planetCard, planetThumbnail],

), ); }}


第十步 在HomePageBody.dart裡,添加一組數據,並修改build函數


import 'package:flutter/material.dart';

import 'package:demo/PlanetRow.dart';

import 'package:demo/Planet.dart';

class HomePageBody extends StatelessWidget {

List planets = [

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模擬器效果如下:

Flutter教程-行星之卡片信息(3)

第十二步 結束

項目地址:

[email protected]:hao2008/flutter-demo.git

下篇預告:行星之卡片列表

歡迎關注『郝先生談技術』頭條號,您的關注,是對作者最大的鼓勵,也是作者創作的動力。


分享到:


相關文章: