版本記錄
| 版本號(hào) | 時(shí)間 |
|---|---|
| V1.0 | 2019.11.03 星期日 |
前言
Flutter是谷歌的移動(dòng)UI框架,可以快速在iOS和Android上構(gòu)建高質(zhì)量的原生用戶界面。 Flutter可以與現(xiàn)有的代碼一起工作。在全世界,F(xiàn)lutter正在被越來越多的開發(fā)者和組織使用,并且Flutter是完全免費(fèi)、開源的。目前公司的部分模塊就是在使用Flutter進(jìn)行開發(fā)。感興趣的可以看下面幾篇文章。
1. Flutter開發(fā)技術(shù)與分享(一) —— 基本概覽(一)
開始
首先看下主要內(nèi)容
通過使用
VS Code編寫跨平臺(tái)應(yīng)用程序,深入研究Flutter框架,以在單個(gè)代碼庫中構(gòu)建iOS和Android應(yīng)用程序。下面是翻譯文章的地址。
然后看下寫作環(huán)境
寫作環(huán)境:Dart 2, Flutter 1.7, VS Code
自十年前iOS和Android平臺(tái)風(fēng)起云涌以來,跨平臺(tái)開發(fā)一直是整個(gè)移動(dòng)開發(fā)領(lǐng)域的目標(biāo)。 能夠?yàn)閕OS和Android編寫一個(gè)應(yīng)用程序的功能可以為您的公司和團(tuán)隊(duì)節(jié)省大量時(shí)間和精力。
多年來,已經(jīng)發(fā)布了用于跨平臺(tái)開發(fā)的各種工具,包括基于Web的工具(例如Adobe的PhoneGap),強(qiáng)大的框架(例如Microsoft的Xamarin)以及更新的工具(例如Facebook的React Native)。 每個(gè)工具集都有其優(yōu)缺點(diǎn),并且在移動(dòng)行業(yè)中獲得了不同程度的成功。
進(jìn)入跨平臺(tái)領(lǐng)域的最新框架是Google的Flutter。 Flutter在兩個(gè)平臺(tái)上均具有快速的開發(fā)周期,快速的UI呈現(xiàn),獨(dú)特的UI設(shè)計(jì)以及本機(jī)應(yīng)用程序性能。
Introduction to Flutter
Flutter應(yīng)用程序是使用Dart編程語言編寫的,該語言最初也來自Google,現(xiàn)在是ECMA標(biāo)準(zhǔn)。 Dart與其他現(xiàn)代語言(例如Kotlin和Swift)具有許多相同的功能,并且可以轉(zhuǎn)編譯為JavaScript代碼。
作為跨平臺(tái)框架,Flutter最類似于React Native,因?yàn)?code>Flutter允許響應(yīng)式和聲明式編程風(fēng)格。但是,與React Native不同,Flutter不需要使用Javascript橋接,這可以縮短應(yīng)用程序的啟動(dòng)時(shí)間和整體性能。 Dart通過使用Ahead-Of-Time或AOT編譯來實(shí)現(xiàn)此目的。
Dart的另一個(gè)獨(dú)特之處在于它還可以使用Just-In-Time or JIT編譯。 Flutter的JIT編譯通過允許熱重裝(hot reload)功能在開發(fā)過程中刷新UI而無需全新的構(gòu)建,從而改善了開發(fā)工作流程。
正如您將在本教程中看到的那樣,Flutter框架主要圍繞widgets的概念構(gòu)建。在Flutter中,widgets不僅用于應(yīng)用程序的視圖,而且還用于整個(gè)屏幕甚至應(yīng)用程序本身。
除了跨平臺(tái)的iOS和Android開發(fā)之外,學(xué)習(xí)Flutter還可以讓您搶先開發(fā)Fuchsia平臺(tái),Fuchsia平臺(tái)目前是Google開發(fā)的實(shí)驗(yàn)性操作系統(tǒng)。
在本教程中,您將構(gòu)建一個(gè)Flutter應(yīng)用程序,該應(yīng)用程序?qū)⒉樵?em>GitHub API中的GitHub組織中的團(tuán)隊(duì)成員,并在可滾動(dòng)列表中顯示團(tuán)隊(duì)成員信息:

您可以同時(shí)使用iOS模擬器或Android模擬器來開發(fā)應(yīng)用程序!
在構(gòu)建應(yīng)用程序時(shí),您將了解有關(guān)Flutter的以下知識(shí):
Setting up your development environmentCreating a new projectHot reloadImporting files and packagesUsing widgets and creating your ownMaking network callsShowing items in a listAdding an app theme
順帶著你也會(huì)學(xué)習(xí)一點(diǎn)關(guān)于Dart的知識(shí)。
Setting up your development environment
Flutter開發(fā)可以在macOS,Linux或Windows上完成。 盡管您可以將任何編輯器與Flutter工具鏈一起使用,但是有 IntelliJ IDEA,Android Studio和Visual Studio Code的IDE插件可以簡化開發(fā)周期。 在本教程中,我們將使用VS Code。
在此處here可以找到有關(guān)使用Flutter框架設(shè)置開發(fā)機(jī)器的說明?;静襟E因平臺(tái)而異,但大多數(shù)情況是:
- 1) 下載適用于您開發(fā)計(jì)算機(jī)操作系統(tǒng)的安裝包,以獲取
Flutter SDK的最新穩(wěn)定版本 - 2) 將安裝包解壓縮到所需位置
- 3) 將flutter工具添加到您的路徑
- 4) 運(yùn)行
flutter doctor命令,該命令將安裝Flutter框架(包括Dart)并提醒您任何缺少的依賴項(xiàng) - 5) 安裝缺少的依賴項(xiàng)
- 6) 使用Flutter插件/擴(kuò)展程序設(shè)置您的IDE
- 7) 測試驅(qū)動(dòng)一個(gè)應(yīng)用
Flutter網(wǎng)站上提供的說明做得很好,可以讓您輕松地在所選平臺(tái)上設(shè)置開發(fā)環(huán)境。本教程的其余部分假定您已經(jīng)為Flutter開發(fā)設(shè)置了VS Code,并且已經(jīng)解決了flutter doctor發(fā)現(xiàn)的所有問題。
如果您使用的是Android Studio,那么您也應(yīng)該能夠很好地遵循。您還需要運(yùn)行iOS模擬器,Android模擬器,或者已設(shè)置預(yù)配置的iOS設(shè)備或Android設(shè)備進(jìn)行開發(fā)。
注意:要在iOS模擬器或iOS設(shè)備上進(jìn)行構(gòu)建和測試,您需要使用已安裝Xcode的
macOS。
Creating a new project
在安裝了Flutter擴(kuò)展的VS Code中,通過選擇View ? Command Palette…或在macOS上單擊Cmd-Shift-P或在Linux或Windows上單擊Ctrl-Shift-P來打開命令面板。 在面板中輸入Flutter:New Project,然后按回車鍵。

輸入項(xiàng)目的名稱ghflutter,然后按回車鍵。 選擇一個(gè)文件夾來存儲(chǔ)項(xiàng)目,然后等待Flutter在VS Code中設(shè)置項(xiàng)目。 項(xiàng)目準(zhǔn)備就緒后,將在編輯器中打開文件main.dart。

在VS Code中,您會(huì)在左側(cè)看到一個(gè)面板,該面板顯示您的項(xiàng)目結(jié)構(gòu)。 有適用于iOS和Android的文件夾,還有一個(gè)包含main.dart的lib文件夾,并且具有適用于兩個(gè)平臺(tái)的代碼。 僅在本教程中,您將在lib文件夾中工作。
用以下內(nèi)容替換main.dart中的代碼:
import 'package:flutter/material.dart';
void main() => runApp(GHFlutterApp());
class GHFlutterApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'GHFlutter',
home: Scaffold(
appBar: AppBar(
title: Text('GHFlutter'),
),
body: Center(
child: Text('GHFlutter'),
),
),
);
}
}
頂部附近的main()函數(shù)對單個(gè)行函數(shù)使用=>運(yùn)算符來運(yùn)行該應(yīng)用程序。 您有一個(gè)名為GHFlutterApp的應(yīng)用程序類。
您在這里看到您的應(yīng)用程序本身是一個(gè)StatelessWidget。 Flutter應(yīng)用程序中的大多數(shù)實(shí)體都是無狀態(tài)或有狀態(tài)的widgets。 您可以覆蓋widgets的build()方法來創(chuàng)建應(yīng)用widgets。 您正在使用MaterialApp widgets,該widgets提供了Material Design之后的應(yīng)用所需的許多組件。
對于本入門教程,通過右鍵單擊,選擇Delete選項(xiàng),然后確認(rèn)刪除,從項(xiàng)目中刪除test文件夾中的測試文件widget_test.dart。

如果您使用的是macOS,請啟動(dòng)iOS模擬器。 您也可以在macOS,Linux或Windows上使用Android模擬器。 如果iOS模擬器和Android模擬器都在運(yùn)行,則可以使用VS Code窗口右下方的菜單在它們之間進(jìn)行切換:

要構(gòu)建和運(yùn)行項(xiàng)目,您需要首先設(shè)置啟動(dòng)配置。
通過單擊左側(cè)面板上的crossed bug圖標(biāo),切換到Debug View。

您會(huì)注意到,到目前為止,尚未定義任何配置。 單擊No Configuration以獲取下拉列表并選擇Add Configuration

VS Code將創(chuàng)建一個(gè)launch.json文件,其詳細(xì)信息如下:

注意:選擇
Add Configuration項(xiàng)后,將自動(dòng)為您生成此文件。 在本教程中,您無需修改它。
現(xiàn)在,您已經(jīng)完成所有工作,可以通過按F5或選擇Debug ? Start Debugging或單擊綠色的播放圖標(biāo)來構(gòu)建和運(yùn)行項(xiàng)目。 您會(huì)看到Debug Console已打開,并且如果在iOS上運(yùn)行,則會(huì)看到用于構(gòu)建項(xiàng)目的Xcode。 如果在Android上運(yùn)行,則會(huì)看到Gradle被調(diào)用以進(jìn)行構(gòu)建。
這是在iOS模擬器中運(yùn)行的應(yīng)用程序:

下面,在Android模擬器中運(yùn)行:

您看到的慢速模式banner表明該應(yīng)用程序正在調(diào)試模式下運(yùn)行。
您可以通過單擊VS Code窗口頂部工具欄右側(cè)的停止按鈕來停止正在運(yùn)行的應(yīng)用程序:

通過單擊VS Code左上方的圖標(biāo)或選擇View ? Explorer,可以返回項(xiàng)目視圖。
Hot Reload
Flutter開發(fā)的最佳方面之一是能夠在進(jìn)行更改時(shí)熱重新加載您的應(yīng)用程序。 這類似于Android Studio的Instant Run/Apply Changes。
構(gòu)建并運(yùn)行該應(yīng)用程序,使其在模擬器或模擬器上運(yùn)行:

現(xiàn)在,無需停止正在運(yùn)行的應(yīng)用程序,請將應(yīng)用程序欄字符串更改為其他內(nèi)容:
appBar: AppBar(
title: Text('GHFlutter App'),
),
現(xiàn)在,單擊工具欄上的熱重載按鈕或直接保存main.dart文件:

一兩秒鐘之內(nèi),您應(yīng)該會(huì)看到正在運(yùn)行的應(yīng)用程序中反映出的更改:

熱重載功能可能并不總是有效,官方文檔official docs可以很好地解釋無法使用的情況,但總體而言,在構(gòu)建UI時(shí)可節(jié)省大量時(shí)間。
Importing a File
您將希望能夠從創(chuàng)建的其他類中導(dǎo)入代碼,而不是將所有Dart代碼都保存在單個(gè)main.dart文件中。 現(xiàn)在,您將看到一個(gè)導(dǎo)入字符串的示例,該示例在需要本地化面向用戶的字符串時(shí)會(huì)有所幫助。
右鍵單擊lib并選擇New File,在lib文件夾中創(chuàng)建一個(gè)名為strings.dart的文件:

將以下類添加到新文件中:
class Strings {
static String appTitle = "GHFlutter";
}
將以下import添加到main.dart的頂部
import 'strings.dart';
更改widget以使用新的字符串類,以便GHFlutterApp類如下所示:
class GHFlutterApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: Strings.appTitle,
home: Scaffold(
appBar: AppBar(
title: Text(Strings.appTitle),
),
body: Center(
child: Text(Strings.appTitle),
),
),
);
}
}
按下F5鍵即可構(gòu)建并運(yùn)行該應(yīng)用,您應(yīng)該不會(huì)有任何變化,但是現(xiàn)在您正在使用字符串文件中的字符串。
Widgets
Flutter應(yīng)用程序中的幾乎每個(gè)元素都是widget。 widget被設(shè)計(jì)為不可變的,因?yàn)槭褂貌豢勺兊?code>widget有助于使應(yīng)用程序UI保持輕便。
您將使用兩種基本類型的小部件:
-
Stateless - 無狀態(tài):僅依賴于自己的配置信息的
widget,例如圖像視圖中的靜態(tài)圖像。 -
Stateful - 有狀態(tài):需要維護(hù)動(dòng)態(tài)信息并通過與
State對象進(jìn)行交互來實(shí)現(xiàn)的信息。
無狀態(tài)小部件和有狀態(tài)widget都在Flutter應(yīng)用程序中的每幀上重新繪制,不同之處在于,有狀態(tài)widget將其配置委托給State對象。
要開始制作自己的widget,請?jiān)?code>main.dart底部創(chuàng)建一個(gè)新類:
class GHFlutter extends StatefulWidget {
@override
createState() => GHFlutterState();
}
您已經(jīng)創(chuàng)建了StatefulWidget子類,并且您將覆蓋createState()方法以創(chuàng)建其狀態(tài)對象。 現(xiàn)在,在GHFlutter上方添加GHFlutterState類:
class GHFlutterState extends State<GHFlutter> {
}
GHFlutterState使用GHFlutter的參數(shù)擴(kuò)展State。
制作widget時(shí)的主要任務(wù)是覆蓋將widget呈現(xiàn)到屏幕時(shí)調(diào)用的build()方法。
在GHFlutterState中添加一個(gè)build()重寫:
@override
Widget build(BuildContext context) {
?
}
填寫build()如下:
@override
Widget build(BuildContext context) {
return Scaffold (
appBar: AppBar(
title: Text(Strings.appTitle),
),
body: Text(Strings.appTitle),
);
}
Scaffold是用于材料設(shè)計(jì)widgets的容器。 它充當(dāng)widgets層次結(jié)構(gòu)的根。 您已在Scaffold中添加了一個(gè)AppBar和一個(gè)body,每個(gè)都包含一個(gè)Text widget。
更新GHFlutterApp,使其使用新的GHFlutter小部件作為其home屬性,而不是構(gòu)建自己的支架:
class GHFlutterApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: Strings.appTitle,
home: GHFlutter(),
);
}
}
構(gòu)建并運(yùn)行該應(yīng)用程序,您將看到新的widget在起作用:

尚未發(fā)生太大變化,但是現(xiàn)在您可以設(shè)置以構(gòu)建新的widget。
Making Network Calls
之前,您已將strings.dart文件導(dǎo)入到項(xiàng)目中。 您可以類似地導(dǎo)入Flutter框架和Dart中包含的其他軟件包。
例如,您現(xiàn)在將使用框架中可用的包進(jìn)行HTTP網(wǎng)絡(luò)調(diào)用,并將生成的響應(yīng)JSON解析為Dart對象。 在main.dart頂部添加兩個(gè)新導(dǎo)入:
import 'dart:convert';
import 'package:http/http.dart' as http;
您會(huì)注意到http包不可用。 這是因?yàn)樯形磳⑵涮砑拥巾?xiàng)目中。 導(dǎo)航到pubspec.yaml文件,然后在dependencies和cupertino_icons:^ 0.1.2下添加以下內(nèi)容:
cupertino_icons: ^0.1.2
# HTTP package
http: ^0.12.0+2
注意:注意縮進(jìn)。 保持 http 軟件包聲明的縮進(jìn)與
cupertino_icons軟件包的縮進(jìn)相同。
現(xiàn)在,當(dāng)您保存pubspec.yaml文件時(shí),VS Code中的Flutter擴(kuò)展名將運(yùn)行flutter pub get命令。 Flutter將獲得聲明的http軟件包,您的軟件包也將在main.dart中可用。
現(xiàn)在,您將在main.dart中看到有關(guān)當(dāng)前未使用的導(dǎo)入的指示器。
Dart應(yīng)用程序是單線程的,但是Dart提供了對在其他線程上運(yùn)行代碼以及運(yùn)行異步代碼的支持,這些異步代碼不會(huì)使用async / await模式阻止UI線程。
您將進(jìn)行異步網(wǎng)絡(luò)調(diào)用以檢索GitHub團(tuán)隊(duì)成員的列表。 在GHFlutterState的頂部添加一個(gè)空列表作為屬性,還添加一個(gè)屬性以容納文本樣式:
var _members = [];
final _biggerFont = const TextStyle(fontSize: 18.0);
名稱開頭的下劃線使該類的成員成為私有成員。
要進(jìn)行異步HTTP調(diào)用,請向GHFlutterState添加方法_loadData():
_loadData() async {
String dataURL = "https://api.github.com/orgs/raywenderlich/members";
http.Response response = await http.get(dataURL);
setState(() {
_members = json.decode(response.body);
});
}
您已經(jīng)在_loadData()上添加了async關(guān)鍵字,以告知Dart它是異步的,并且還在http.get()調(diào)用上阻塞了await關(guān)鍵字。 您使用的dataUrl值設(shè)置為GitHub API端點(diǎn),該端點(diǎn)檢索GitHub組織的成員。
HTTP調(diào)用完成后,您將向回調(diào)傳遞給setState(),該回調(diào)在UI線程上同步運(yùn)行。 在這種情況下,您將解碼JSON響應(yīng)并將其分配給_members列表。
將initState()重寫添加到GHFlutterState,該狀態(tài)在初始化狀態(tài)時(shí)調(diào)用_loadData():
@override
void initState() {
super.initState();
_loadData();
}
Using a ListView
現(xiàn)在您已經(jīng)有了Dart成員列表,您需要一種在UI列表中顯示它們的方法。 Dart提供了一個(gè)ListView widget,可讓您在列表中顯示數(shù)據(jù)。 ListView的行為類似于Android上的RecyclerView和iOS上的UITableView,在用戶滾動(dòng)列表以實(shí)現(xiàn)平滑滾動(dòng)性能時(shí)回收視圖。
將_buildRow()方法添加到GHFlutterState中:
Widget _buildRow(int i) {
return ListTile(
title: Text("${_members[i]["login"]}", style: _biggerFont)
);
}
您將返回一個(gè)ListTile widget,該widget顯示從ith成員的JSON解析的login值,并使用您之前創(chuàng)建的文本樣式。
更新GHFlutterState的構(gòu)建方法,使其主體為ListView.builder:
body: ListView.builder(
padding: const EdgeInsets.all(16.0),
itemCount: _members.length,
itemBuilder: (BuildContext context, int position) {
return _buildRow(position);
}),
你已經(jīng)添加padding,itemCount設(shè)置為成員的數(shù)量,并使用_buildRow()為給定的位置設(shè)置itemBuilder。
您可以嘗試熱重載,但可能會(huì)收到“Full restart may be required”消息。 如果是這樣,請按F5鍵構(gòu)建并運(yùn)行該應(yīng)用程序:

進(jìn)行網(wǎng)絡(luò)通話,解析數(shù)據(jù)并在列表中顯示結(jié)果就是這么簡單!

Adding dividers
要將分隔符添加到列表中,您需要將item數(shù)量加倍,然后在列表中的位置為奇數(shù)時(shí)返回Divider widget。 如下更新GHFlutterState的構(gòu)建方法:
body: ListView.builder(
itemCount: _members.length * 2,
itemBuilder: (BuildContext context, int position) {
if (position.isOdd) return Divider();
final index = position ~/ 2;
return _buildRow(index);
}),
確保不要錯(cuò)過itemCount上的* 2。 有了分隔線后,您已經(jīng)從構(gòu)建器中刪除了padding。 在itemBuilder中,您要么返回Divider(),要么通過整數(shù)除法并使用_buildRow()來構(gòu)建行項(xiàng)目來計(jì)算新索引。
嘗試熱重載,您應(yīng)該在列表上看到分隔線:

要將padding重新添加到每一行中,您想在_buildRow()中使用Padding widget:
Widget _buildRow(int i) {
return Padding(
padding: const EdgeInsets.all(16.0),
child: ListTile(
title: Text("${_members[i]["login"]}", style: _biggerFont)
)
);
}
ListTile現(xiàn)在是padding widget的子widget。 熱重新加載以查看行上的padding,而不是分隔線上的padding。
Parsing to Custom Types
在上一節(jié)中,JSON解析器將JSON響應(yīng)中的每個(gè)成員作為Dart Map類型添加到_members列表中,相當(dāng)于Kotlin中的Map或Swift中的Dictionary。
但是,您還希望能夠使用自定義類型。
在main.dart文件中添加一個(gè)新的Member類型:
class Member {
final String login;
Member(this.login) {
if (login == null) {
throw ArgumentError("login of Member cannot be null. "
"Received: '$login'");
}
}
}
成員具有login屬性和一個(gè)構(gòu)造函數(shù),如果登錄值為null,則該構(gòu)造函數(shù)將拋出錯(cuò)誤。
更新GHFlutterState中的_members聲明,以便它是Member對象的列表:
var _members = <Member>[];
更新_buildRow()以在Member對象上使用login屬性,而不是使用映射上的login鍵:
title: Text("${_members[i].login}", style: _biggerFont)
現(xiàn)在,更新發(fā)送到_loadData()中的setState()的回調(diào),以將解碼后的映射轉(zhuǎn)換為Member對象并將其添加到成員列表中:
setState(() {
final membersJSON = json.decode(response.body);
for (var memberJSON in membersJSON) {
final member = Member(memberJSON["login"]);
_members.add(member);
}
});
如果嘗試進(jìn)行熱重裝,您可能會(huì)看到一個(gè)錯(cuò)誤,但是停止并按F5鍵來構(gòu)建和運(yùn)行該應(yīng)用,您應(yīng)該會(huì)看到與以前相同的屏幕,除了現(xiàn)在使用新的Member類。
Downloading Images with NetworkImage
來自GitHub的每個(gè)成員都有其頭像的URL。 現(xiàn)在,您將該頭像添加到Member類中,并在應(yīng)用程序中顯示頭像。
更新Member類以添加一個(gè)avatarUrl屬性,該屬性不能為null:
class Member {
final String login;
final String avatarUrl;
Member(this.login, this.avatarUrl) {
if (login == null) {
throw ArgumentError("login of Member cannot be null. "
"Received: '$login'");
}
if (avatarUrl == null) {
throw ArgumentError("avatarUrl of Member cannot be null. "
"Received: '$avatarUrl'");
}
}
}
使用NetworkImage和CircleAvatar widget更新_buildRow()以顯示頭像:
Widget _buildRow(int i) {
return Padding(
padding: const EdgeInsets.all(16.0),
child: ListTile(
title: Text("${_members[i].login}", style: _biggerFont),
leading: CircleAvatar(
backgroundColor: Colors.green,
backgroundImage: NetworkImage(_members[i].avatarUrl)
),
)
);
}
通過將頭像設(shè)置為ListTile的leading屬性,它將在行內(nèi)標(biāo)題之前顯示。 您還使用Colors類在圖片上設(shè)置了背景色。
現(xiàn)在更新_loadData()以在創(chuàng)建新Member時(shí)使用映射中的“ avatar_url”值:
final member = Member(memberJSON["login"], memberJSON["avatar_url"]);
使用F5停止,構(gòu)建和運(yùn)行該應(yīng)用程序。 您會(huì)在每一行中看到您的成員頭像:

Cleaning the Code
現(xiàn)在,您的大多數(shù)代碼都位于main.dart文件中。 為了使代碼更簡潔,您可以重構(gòu)已添加到文件中的widget和其他類。
在lib文件夾中創(chuàng)建名為member.dart和ghflutter.dart的文件。 將Member類移至member.dart,并將GHFlutterState和GHFlutter類移至ghflutter.dart。
您在member.dart中不需要任何import語句,但是ghflutter.dart中的導(dǎo)入應(yīng)如下所示:
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
import 'member.dart';
import 'strings.dart';
您還需要更新main.dart中的導(dǎo)入,以便整個(gè)文件包含以下內(nèi)容:
import 'package:flutter/material.dart';
import 'ghflutter.dart';
import 'strings.dart';
void main() => runApp(GHFlutterApp());
class GHFlutterApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: Strings.appTitle,
home: GHFlutter(),
);
}
}
按下F5來構(gòu)建和運(yùn)行該應(yīng)用程序,您應(yīng)該看不到任何更改,但是代碼現(xiàn)在更簡潔了。
Adding a Theme
您可以通過將theme屬性添加到您在main.dart中創(chuàng)建的MaterialApp中,輕松地將主題添加到應(yīng)用中:
class GHFlutterApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: Strings.appTitle,
theme: ThemeData(primaryColor: Colors.green.shade800),
home: GHFlutter(),
);
}
}
您將綠色用作主題的“材料設(shè)計(jì)”顏色值。
按下F5來構(gòu)建和運(yùn)行應(yīng)用程序,以查看新的主題:

大多數(shù)應(yīng)用程序屏幕截圖均來自Android模擬器。 您還可以在iOS模擬器中運(yùn)行最終的主題應(yīng)用程序:

這就是我所說的跨平臺(tái)!
有關(guān)Flutter和Dart的知識(shí)還有很多。 最好的起點(diǎn)是:
-
flutter.dev上的
Flutter主頁。 您會(huì)發(fā)現(xiàn)很多很棒的文檔和其他信息。 - 在此處here查看可用的
widgets。 - 這里here有一個(gè)很好的指南供
Android開發(fā)人員過渡到使用Flutter。 - 適用于
React Native開發(fā)人員的類似指南在這里here。
后記
本篇主要講述了Flutter 入門,感興趣的給個(gè)贊或者關(guān)注~~~
