Flutter正迅速成為開發(fā)跨平臺(tái)移動(dòng)應(yīng)用程序的最流行框架之一茧痒。今天,大多數(shù)Android和iOS開發(fā)人員開始認(rèn)為侈百,它是一種比其他跨平臺(tái)框架(如React Native和NativeScript)更快吩谦,更具面向未來的替代方案。
谷歌本身不遺余力地吸引更多開發(fā)者加入本刽。例如,Google I / O今年有幾個(gè)深入的會(huì)議赠涮,專注于使用它開發(fā)符合Material Design標(biāo)準(zhǔn)的應(yīng)用程序子寓。在其中一次會(huì)議中洪灯,Google還宣布Flutter將成為Material Design的一流平臺(tái)嚣伐。
在本系列教程中,我將幫助您掌握使用Flutter開發(fā)Android應(yīng)用程序的基礎(chǔ)知識(shí)只冻。在本系列開始的教程中株憾,我將重點(diǎn)關(guān)注Flutter小部件,這是所有Flutter應(yīng)用程序的構(gòu)建塊。
先決條件
要充分利用這個(gè)系列嗤瞎,您需要:
- 最新版本的Android Studio
- 運(yùn)行Android API等級(jí)21或更高版本的設(shè)備或模擬器
1.配置Android Studio
安裝了一些輕量級(jí)插件后墙歪,您可以使用Android本地Android應(yīng)用程序開發(fā)人員最熟悉的Android Studio來開發(fā)Flutter應(yīng)用程序。
首先啟動(dòng)Android Studio贝奇,然后 在歡迎屏幕中選擇配置>插件選項(xiàng)虹菲。
在彈出的對(duì)話框中,按“ 瀏覽存儲(chǔ)庫” 按鈕并搜索Flutter插件掉瞳。
找到插件后毕源,按“ 安裝” 按鈕。此時(shí)陕习,系統(tǒng)會(huì)詢問您是否還要安裝Dart插件霎褐。按是 繼續(xù)。
安裝 完兩個(gè)插件后该镣,按“ 重啟Android Studio”按鈕完成配置冻璃。
2.創(chuàng)建一個(gè)新項(xiàng)目
重啟后,您將能夠 在Android Studio歡迎屏幕上看到“ 啟動(dòng)新的Flutter項(xiàng)目”按鈕损合。按此按鈕開始創(chuàng)建您的第一個(gè)Flutter項(xiàng)目省艳。
在下一個(gè)屏幕上,選擇Flutter Application 選項(xiàng)嫁审,然后按Next跋炕。
您現(xiàn)在將看到一個(gè)表單,詢問有關(guān)Flutter應(yīng)用程序的各種詳細(xì)信息律适,例如其名稱和位置辐烂。確保在所有字段中鍵入有效值。
Flutter插件不與Flutter SDK捆綁在一起擦耀。因此棉圈,您必須單獨(dú)安裝SDK。您現(xiàn)在可以通過按“ 安裝SDK” 按鈕來執(zhí)行此操作眷蜓。
根據(jù)Internet連接的速度分瘾,安裝可能需要相當(dāng)長的時(shí)間才能完成。成功后吁系,您將能夠按“ 下一步” 按鈕完成項(xiàng)目設(shè)置德召。
3.添加入口點(diǎn)
在本教程中,您將在lib / main.dart 文件中編寫代碼汽纤。默認(rèn)情況下上岗,它將包含一些您不需要的示例代碼。所以在繼續(xù)之前刪除所有內(nèi)容蕴坪。
Flutter框架使用Dart編程語言肴掷,這是一種易于學(xué)習(xí)的語言敬锐,其語法與Java和C的語法非常相似。因此呆瞻,像大多數(shù)獨(dú)立的Java和C程序一樣台夺,F(xiàn)lutter應(yīng)用程序也需要一個(gè)main()
函數(shù),一個(gè)特殊的函數(shù)痴脾,作為應(yīng)用程序的入口點(diǎn)颤介。
因此,將以下代碼添加到main.dart 文件中:
void main() {
// TO DO
}
此時(shí)赞赖,您可以按 Shift-F10 來構(gòu)建和運(yùn)行應(yīng)用程序滚朵。如果您在前面的步驟中沒有遇到任何錯(cuò)誤,您應(yīng)該會(huì)看到該應(yīng)用在您的設(shè)備上顯示空白的白色畫布前域。
4.使用無狀態(tài)小部件
所有Flutter應(yīng)用程序都由一個(gè)或多個(gè)小部件組成辕近,類的實(shí)例允許您在屏幕上繪制文本和圖像。通常话侄,您不必從頭開始編寫任何低級(jí)小部件亏推,因?yàn)樵摽蚣芨綆Я烁鞣N預(yù)制的,漂亮的小部件年堆,這些小部件遵循Android和iOS平臺(tái)的設(shè)計(jì)語言吞杭。
為了能夠在您的應(yīng)用程序中使用基本小部件,請(qǐng)widgets 通過在main.dart 文件的開頭添加以下代碼來導(dǎo)入庫:
import 'package:flutter/widgets.dart';
您可以創(chuàng)建的最簡單的小部件是無狀態(tài)小部件变丧。正如您可能已經(jīng)猜到的那樣芽狗,它們沒有與之相關(guān)的狀態(tài),因此是靜態(tài)的痒蓬。它們非常適合顯示標(biāo)簽童擎,標(biāo)題和其他UI元素,其內(nèi)容在應(yīng)用程序運(yùn)行時(shí)不太可能發(fā)生變化攻晒。要?jiǎng)?chuàng)建無狀態(tài)窗口小部件顾复,必須擴(kuò)展StatelessWidget 該類并覆蓋其build() 方法。以下示例代碼顯示了如何:
class MyFirstWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
// More code here
}
}
正如您在上面的代碼中看到的鲁捏,該build() 方法必須返回一個(gè)Widget 對(duì)象芯砸。您可以自由選擇并返回Flutter提供的數(shù)十種預(yù)制小部件中的任何一種。例如给梅,如果要顯示一行文本假丧,可以創(chuàng)建并返回一個(gè)Text 小部件,如下所示:
return Text("This is nice!",
textDirection: TextDirection.ltr);
請(qǐng)注意动羽,您必須始終記住在使用Text 窗口小部件時(shí)指定文本的方向 包帚。
但是,如果您立即運(yùn)行該應(yīng)用程序运吓,您將無法看到該文本渴邦。那是因?yàn)槟氵€沒有實(shí)例化你的無狀態(tài)小部件疯趟。所以轉(zhuǎn)到main() 方法,在其中實(shí)例化小部件几莽,并將其傳遞給runApp() 方法迅办。這是如何做:
runApp(new MyFirstWidget());
在您添加上述代碼并保存項(xiàng)目的那一刻,Android Studio應(yīng)該會(huì)自動(dòng)在您的設(shè)備上熱重新加載應(yīng)用章蚣,以便您查看文本。
如果要顯示圖像而不是文本姨夹,可以Text
使用Image
類的build()
方法中的窗口小部件替換窗口小部件纤垂。以下代碼顯示如何創(chuàng)建Image
下載并顯示遠(yuǎn)程圖像的窗口小部件:
`return` `Image.network(`
`"[https://images.pexels.com/photos/1168940/pexels-photo-1168940.jpeg](https://images.pexels.com/photos/1168940/pexels-photo-1168940.jpeg)"``);`
再次保存項(xiàng)目時(shí),您應(yīng)該在設(shè)備上看到類似的內(nèi)容:
歡迎加入Android技術(shù)開發(fā)交流2群:935654177磷账。大家相互交流學(xué)習(xí)
5.創(chuàng)建小部件樹
所有Flutter應(yīng)用程序都可以被視為小部件樹峭沦。您在上一步中創(chuàng)建的應(yīng)用程序是一個(gè)只包含一個(gè)小部件的小部件樹。但是逃糟,使用Text
或Image
窗口小部件作為窗口小部件樹的頂部元素并不是一個(gè)好主意吼鱼,因?yàn)槟鷮o法向它們添加任何子窗口小部件。
Flutter提供了幾個(gè)可以作為其他小部件容器的小部件绰咽。最常用的是Row
和Column
小部件菇肃。正如他們的名字所暗示的那樣, Row
小部件允許您將多個(gè)小部件放在一起取募,并且Column
小部件可以幫助您將小部件放在 另一個(gè)之下琐谤。在創(chuàng)建更深層的窗口小部件樹時(shí),它們是必不可少的玩敏。
以下代碼顯示如何使用Column
窗口小部件創(chuàng)建具有兩個(gè)子窗口的窗口小部件樹:Text
窗口小部件和Image
窗口小部件斗忌。
`Text myText = Text(``"This is a nice photo!"``,`
`textDirection: TextDirection.ltr);`
`Image myImage = Image.network(`
`"[https://images.pexels.com/photos/1168940/pexels-photo-1168940.jpeg](https://images.pexels.com/photos/1168940/pexels-photo-1168940.jpeg)"``);`
`return` `Column(`
`children: <Widget>[myText, myImage]`
`);`
該應(yīng)用程序現(xiàn)在應(yīng)該如下所示:
此外,還有一些小部件可以幫助您更好地定位單個(gè)小部件旺聚。例如织阳,Center
窗口小部件可幫助您集中窗口小部件。同樣砰粹,Container
窗口小部件允許您向窗口小部件添加填充和邊距唧躲。
以下代碼向您展示如何Column
通過將您剛創(chuàng)建的窗口小部件嵌入窗口小部件來居中它Center
:
return Center(child: Column(
children: <Widget>[myText, myImage],
mainAxisSize: MainAxisSize.min
)
);
在上面的代碼中,請(qǐng)注意Column 窗口小部件使用一個(gè)名為的附加屬性 mainAxisSize伸眶,其值設(shè)置為min惊窖。這是必要的,因?yàn)樵趯?duì)列居中之前厘贼,必須使其高度等于其所有子節(jié)點(diǎn)的高度之和界酒。如果沒有該屬性,Column 窗口小部件將與設(shè)備的屏幕一樣大嘴秸,并且Center 窗口小部件將不會(huì)對(duì)其產(chǎn)生任何影響毁欣。
6.使用Material Design Widgets
在此期間庇谆,您一直在使用作為widgets 庫的一部分的基本小部件。Flutter有一個(gè)名為的替代庫material凭疮,它提供了Material Design小部件饭耳。要在您的應(yīng)用程序中使用它,請(qǐng)使用以下內(nèi)容替換導(dǎo)入widgets 庫的語句:
import 'package:flutter/material.dart';
接下來执解,要將Material Design樣式應(yīng)用于窗口小部件寞肖,您必須MaterialApp 在窗口小部件樹的頂部放置一個(gè) 窗口小部件。您還必須將先前創(chuàng)建的所有小部件嵌入到窗口小Scaffold 部件中衰腌,該窗口小部件可用作窗口小部件的主屏幕 MaterialApp 新蟆。
此外,由于大多數(shù)Material Design應(yīng)用程序都有應(yīng)用欄右蕊,因此您可以選擇將Scaffold 小部件appBar 屬性設(shè)置為新AppBar 小部件琼稻。
以下代碼向您展示如何簡潔地完成所有操作:
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text("My App")),
body: Center(
child: Column(
children: <Widget>[myText, myImage],
mainAxisSize: MainAxisSize.min
),
)
)
);
該應(yīng)用程序現(xiàn)在應(yīng)該看起來好多了。
7.使用有狀態(tài)小部件
無狀態(tài)小部件是不可變的饶囚。使用您在前面的步驟中編寫的代碼帕翻,沒有簡單的方法來修改Text
窗口小部件或Image
窗口小部件的內(nèi)容。為什么萝风?因?yàn)镕lutter框架更喜歡反應(yīng)式編程而不是命令式編程嘀掸。因此,它的大多數(shù)小部件都沒有可以在運(yùn)行時(shí)更新其內(nèi)容的setter方法闹丐。例如横殴,Text
窗口小部件沒有setText()
允許您更改其顯示文本的方法。
另一方面卿拴,有狀態(tài)小部件是可變的衫仑,盡管不是直接的。他們依靠 State
對(duì)象來決定在任何給定實(shí)例中應(yīng)該顯示什么堕花。因此文狱,只要State
對(duì)象發(fā)生更改,框架就會(huì)自動(dòng)更新連接到它的任何有狀態(tài)窗口小部件的內(nèi)容缘挽。
要?jiǎng)?chuàng)建有狀態(tài)窗口小部件瞄崇,必須擴(kuò)展StatefulWidget
該類并覆蓋其 createState()
方法。
class MySecondWidget extends StatefulWidget {
@override
State<StatefulWidget> createState() {
// TO DO
}
}
接下來壕曼,您必須創(chuàng)建一個(gè)新的自定義State 類苏研,其中包含構(gòu)成有狀態(tài)窗口小部件狀態(tài)的變量。此外腮郊,在類中摹蘑,您必須重寫 build() 方法以返回窗口小部件樹。
以下代碼顯示如何創(chuàng)建State 包含名為的單個(gè)變量的類url:
`class` `MyState` `extends` `State<MySecondWidget> {`
`String url =` `"[https://source.unsplash.com/random/800x600](https://source.unsplash.com/random/800x600)"``;`
`// A random image from Unsplash`
`@override`
`Widget build(BuildContext context) {`
`// More code here`
`}`
`}`
為了一個(gè)具體的例子轧飞,我們現(xiàn)在創(chuàng)建一個(gè)Material Design窗口小部件樹Image 衅鹿,其中包含一個(gè)顯示隨機(jī)圖像的RaisedButton 窗口小部件和一個(gè)窗口小部件撒踪,用戶可以按這個(gè)窗口小部件來加載新的隨機(jī)圖像。以下代碼顯示了如何:
return MaterialApp(
home: Scaffold(
body: Center(
child:Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
RaisedButton(
child: Text("Press Me"),
onPressed: changeURL,
),
Image.network(url)
]
)
)
)
);
請(qǐng)注意大渤,Image 窗口小部件的構(gòu)造函數(shù)現(xiàn)在將url 變量作為其輸入制妄,而不是字符串文字。這允許框架在Image 繪制窗口小部件時(shí)使用變量的最新值泵三。
另請(qǐng)注意耕捞,RaisedButton 窗口小部件具有onPressed 指向名為的事件偵聽器的屬性changeURL()。該方法尚不存在切黔,因此請(qǐng)創(chuàng)建它砸脊。
void changeURL() {
// More code here
}
當(dāng)然,在方法中纬霞,您必須更改url
變量的值。但是驱显,您不應(yīng)該直接更改它诗芜。如果這樣做,F(xiàn)lutter框架將不會(huì)收到有關(guān)更改的通知埃疫。要正確更新有狀態(tài)窗口小部件的狀態(tài)伏恐,必須始終在setState()
方法內(nèi)進(jìn)行所有更改。
目前栓霜,為了顯示隨機(jī)圖像翠桦,我建議您使用Unsplash Source 服務(wù)。從中下載隨機(jī)圖像所需要做的就是向其URL發(fā)出HTTP請(qǐng)求并向其傳遞唯一的查詢字符串胳蛮。
以下代碼顯示如何使用時(shí)間戳構(gòu)造唯一查詢字符串:
`setState(() {`
`url =` `"[https://source.unsplash.com/random/800x600/?](https://source.unsplash.com/random/800x600/?)"` `+`
`"q=${new DateTime.now().millisecondsSinceEpoch}"``;`
`});`
此時(shí)销凑,您的自定義State 類已準(zhǔn)備就緒。接下來需要做的就是實(shí)例化它并從createState() 有狀態(tài)小部件的方法返回它仅炊。
runApp(new MyFirstWidget());
如果您將有狀態(tài)窗口小部件的實(shí)例傳遞給runApp()
方法斗幼,重新加載應(yīng)用程序,并按幾次按鈕抚垄,您應(yīng)該會(huì)看到它每次都顯示一張新照片蜕窿。
結(jié)論
您現(xiàn)在知道如何在Flutter應(yīng)用程序中使用無狀態(tài)和有狀態(tài)的小部件。您還學(xué)習(xí)了如何將Material Design主題應(yīng)用于它們呆馁,動(dòng)態(tài)更改其內(nèi)容并使它們具有交互性桐经。
值得注意的是,F(xiàn)lutter不使用任何移動(dòng)平臺(tái)的本機(jī)小部件浙滤。它使用名為Skia的高性能2D圖形引擎自行繪制所有小部件阴挣,該引擎廣泛使用GPU。因此瓷叫,F(xiàn)lutter應(yīng)用程序通常以接近60 fps的速度運(yùn)行屯吊,并且感覺非常流暢和響應(yīng)送巡。