Flutter開發(fā)技術(shù)與分享(二) —— Flutter 入門(一)

版本記錄

版本號(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)建iOSAndroid應(yīng)用程序。下面是翻譯文章的地址

然后看下寫作環(huán)境

寫作環(huán)境:Dart 2, Flutter 1.7, VS Code

自十年前iOSAndroid平臺(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的工具(例如AdobePhoneGap),強(qiáng)大的框架(例如MicrosoftXamarin)以及更新的工具(例如FacebookReact Native)。 每個(gè)工具集都有其優(yōu)缺點(diǎn),并且在移動(dòng)行業(yè)中獲得了不同程度的成功。

進(jìn)入跨平臺(tái)領(lǐng)域的最新框架是GoogleFlutter。 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)代語言(例如KotlinSwift)具有許多相同的功能,并且可以轉(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-TimeAOT編譯來實(shí)現(xiàn)此目的。

Dart的另一個(gè)獨(dú)特之處在于它還可以使用Just-In-Time or JIT編譯。 FlutterJIT編譯通過允許熱重裝(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 environment
  • Creating a new project
  • Hot reload
  • Importing files and packages
  • Using widgets and creating your own
  • Making network calls
  • Showing items in a list
  • Adding an app theme

順帶著你也會(huì)學(xué)習(xí)一點(diǎn)關(guān)于Dart的知識(shí)。


Setting up your development environment

Flutter開發(fā)可以在macOS,LinuxWindows上完成。 盡管您可以將任何編輯器與Flutter工具鏈一起使用,但是有 IntelliJ IDEA,Android StudioVisual Studio CodeIDE插件可以簡化開發(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.dartlib文件夾,并且具有適用于兩個(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。 您可以覆蓋widgetsbuild()方法來創(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 StudioInstant 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è)元素都是widgetwidget被設(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文件,然后在dependenciescupertino_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中的MapSwift中的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'");
    }
  }
}

使用NetworkImageCircleAvatar 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è)置為ListTileleading屬性,它將在行內(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.dartghflutter.dart的文件。 將Member類移至member.dart,并將GHFlutterStateGHFlutter類移至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)FlutterDart的知識(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)注~~~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容