Flutter實戰(zhàn)指南(移動終端-應用程序-程序設計)_第1頁
Flutter實戰(zhàn)指南(移動終端-應用程序-程序設計)_第2頁
Flutter實戰(zhàn)指南(移動終端-應用程序-程序設計)_第3頁
Flutter實戰(zhàn)指南(移動終端-應用程序-程序設計)_第4頁
Flutter實戰(zhàn)指南(移動終端-應用程序-程序設計)_第5頁
已閱讀5頁,還剩305頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領

文檔簡介

Flutter實戰(zhàn)指南移動終端-應用程序-程序設計目錄TOC\h\h基礎篇\h第1章Flutter簡介\h1.1什么是Flutter\h1.2Flutter的架構(gòu)\h1.3在macOS下安裝Flutter\h1.4在macOS下安裝VisualStudioCode\h1.5在Windows下安裝Flutter\h1.6在Windows下安裝VisualStudioCode\h1.7Flutter中的MaterialDesign體系\h第2章深入理解Flutter基礎知識和小部件概念\h2.1創(chuàng)建一個Flutter項目\h2.2Flutter目錄結(jié)構(gòu)及main文件\h2.3Flutter中小部件的概念\h2.4創(chuàng)建Flutter小部件\h2.5小部件中的build方法\h2.6添加Scaffold頁面\h2.7深入學習Dart語法\h2.8使用Card小部件和圖片\h2.9官方文檔及使用按鈕RaisedButton\h2.10創(chuàng)建StatefulWidget小部件\h2.11在StatefulWidget中管理數(shù)據(jù)\h2.12在StatefulWidget小部件中添加數(shù)據(jù)\h2.13把小部件拆分到單獨的文件中\(zhòng)h2.14使用自定義小部件\h2.15給StatefulWidget傳遞參數(shù)\h2.16深入學習生命周期\h2.17深入學習Google的MaterialDesign設計體系\h2.18Dart語言特性及位置參數(shù)與可選參數(shù)\h2.19Flutter中解除狀態(tài)的特性\h2.20理解Dart語言中的final和const\h2.21總結(jié)\h第3章調(diào)試Flutter應用程序\h3.1解決語法錯誤\h3.2運行時錯誤和運行時日志消息\h3.3處理邏輯錯誤\h3.4使用debug斷點調(diào)試\h3.5UI調(diào)試及視覺幫助工具\h第4章在不同設備上運行Flutter應用程序\h4.1將App運行到Android模擬器上\h4.2將Flutter應用運行到Android設備上\h4.3將App運行到iOS模擬器和設備上\h第5章列表ListView小部件和條件過濾\h5.1使用ListView創(chuàng)建滾動列表\h5.2優(yōu)化列表加載功能\h5.3根據(jù)條件渲染列表內(nèi)容\h5.4根據(jù)條件渲染內(nèi)容的替代方案\h5.5總結(jié)\h第6章Flutter頁面導航\h6.1在App中添加多個頁面\h6.2給導航頁面添加按鈕\h6.3實現(xiàn)基本導航功能\h6.4優(yōu)化詳情頁面\h6.5通過Push給頁面?zhèn)鬟f數(shù)據(jù)\h6.6通過Pop獲取頁面返回的數(shù)據(jù)\h6.7給導航頁面中的按鈕添加單擊事件\h6.8添加登錄頁面并切換頁面\h6.9抽屜式導航\h6.10使用Tab標簽頁導航頁面\h6.11命名路徑\h6.12解析導航路徑數(shù)據(jù)\h6.13導航頁面的整理與優(yōu)化\h6.14使用導航路徑生成器\h6.15對話框\h6.16模態(tài)彈出層\h6.17總結(jié)\h第7章處理用戶輸入\h7.1使用文本框TextField并保存用戶輸入內(nèi)容\h7.2配置文本框TextField\h7.3設置文本框TextField樣式\h7.4保存文本框中內(nèi)容\h7.5優(yōu)化文本框顯示\h7.6使用開關(guān)Switch小部件\h7.7總結(jié)\h第8章深入學習Flutter小部件\h8.1Flutter官網(wǎng)探索小部件\h8.2使用不同的小部件完成同一個目標\h8.3文本小部件Text和行小部件Row\h8.4修飾小部件BoxDecoration\h8.5理解Expanded和Flexible\h8.6添加背景圖像\h8.7圖標小部件Icon\h8.8封裝小部件\h8.9重構(gòu)項目代碼\h8.10創(chuàng)建標準化的小部件\h8.11封裝小部件的方法\h8.12Flutter中響應式設計\h8.13使用MediaQuery\h8.14ListView中使用MediaQuery\h8.15使用GestureDetector添加監(jiān)聽\h8.16總結(jié)\h第9章Form表單\h9.1表單文本框TextFormField\h9.2Form表單驗證\h9.3表單Form的高級驗證\h9.4關(guān)閉設備鍵盤\h9.5提交表單數(shù)據(jù)\h9.6把表單數(shù)據(jù)保存到列表\h9.7重用創(chuàng)建資訊頁面\h9.8表單設置初始值\h9.9更新數(shù)據(jù)\h9.10總結(jié)\h高級篇\h第10章優(yōu)化Flutter應用功能\h10.1優(yōu)化ListTile\h10.2通過Dismissible小部件實現(xiàn)滑動刪除\h10.3監(jiān)聽滑動手勢刪除數(shù)據(jù)及總結(jié)\h第11章狀態(tài)集中管理ScopeModel\h11.1優(yōu)化Flutter狀態(tài)管理\h11.2自定義實體類\h11.3創(chuàng)建ScopedModel\h11.4與ScopedModel建立聯(lián)系\h11.5使用ScopedModel編輯和刪除\h11.6收藏功能\h11.7使用notifyListeners()方法\h11.8過濾收藏的內(nèi)容\h11.9添加用戶實體\h11.10使用mix特性合并模型\h11.11連接模型和共享數(shù)據(jù)\h11.12總結(jié)\h第12章Flutter與HTTP\h12.1后端服務接口\h12.2Flutter發(fā)送POST請求\h12.3使用請求響應結(jié)果\h12.4從服務器端獲取數(shù)據(jù)\h12.5實現(xiàn)加載條\h12.6按鈕顯示加載條\h12.7通過HTTP更新數(shù)據(jù)\h12.8通過Http刪除內(nèi)容\h12.9下拉頁面刷新\h12.10占位圖片\h12.11優(yōu)化ScopedModel\h12.12處理HTTP響應錯誤\h12.13使用async和await\h12.14總結(jié)\h第13章權(quán)限認證\h13.1Flutter中如何使用權(quán)限\h13.2確認密碼文本框\h13.3用戶注冊\h13.4處理注冊過程中的異常\h13.5用戶注冊加載條\h13.6用戶登錄\h13.7訪問受保護資源\h13.8存儲token\h13.9自動登錄\h13.10用戶退出\h13.11自動退出\h13.12自動退出跳轉(zhuǎn)\h13.13優(yōu)化用戶登錄\h13.14添加收藏功能\h13.15獲取收藏狀態(tài)\h13.16根據(jù)條件顯示列表和總結(jié)\h第14章訪問相機和圖庫\h14.1選擇圖片小部件\h14.2使用圖片選擇器UI\h14.3使用ImagePicker選擇圖片\h14.4圖片預覽\h14.5上傳圖片\h14.6上傳圖片到服務器端\h14.7編輯上傳的圖片\h14.8總結(jié)\h第15章Flutter動畫效果\h15.1浮動按鈕\h15.2添加動畫效果\h15.3旋轉(zhuǎn)動畫效果\h15.4漸變動畫效果\h15.5滑動動畫效果\h15.6Flutter中的Hero和Sliver\h15.7自定義切換頁面動畫效果\h第16章優(yōu)化應用\h16.1優(yōu)化自動退出\h16.2優(yōu)化編輯功能和收藏功能\h16.3使用analyze命令優(yōu)化項目\h第17章使用平臺特有的小部件\h17.1根據(jù)平臺的不同顯示不同的小部件\h17.2根據(jù)不同的平臺顯示不同的主題\h第18章Flutter跨平臺交互\h18.1Flutter與原生代碼交互\h18.2編寫Android端原生代碼并與Flutter交互\h18.3編寫iOS端原生代碼與Flutter交互\h第19章發(fā)布Flutter應用\h19.1設置應用圖標\h19.2給App添加閃屏\h19.3Android打包和發(fā)布\h19.4iOS打包和發(fā)布\h第20章總結(jié)與回顧基礎篇相信許多移動應用開發(fā)者在開發(fā)過程中遇到過和我同樣問題,開發(fā)一套原生的應用程序,需要運行在iOS和Android兩個不同的平臺,為此我們至少要學習Java、Object-C、Swift等兩到三種語言來滿足這樣的需求,占用了我們大量的時間和精力,而且還要維護不同的代碼庫,或者有的開發(fā)者使用Web的H5來實現(xiàn)這種跨平臺的應用,但H5通常跟設備操作系統(tǒng)不是太友好,往往受瀏覽器版本和移動設備中操作系統(tǒng)的限制。再有就是采用加殼的技術(shù)來滿足這種跨平臺的需求,但是就性能來說會很糟糕?;谝陨线@些問題的存在,F(xiàn)lutter誕生了,成為移動應用領域里很熱門的一項技術(shù)。大的互聯(lián)網(wǎng)平臺都開始關(guān)注并使用這項技術(shù)去開發(fā)它們的移動應用。大家將從本書基礎篇學習到如何使用一種語言、一個代碼庫構(gòu)建跨平臺移動App,內(nèi)容包括如何構(gòu)建小部件,如何使用這些小部件搭建你的應用。大家將循序漸進地了解怎么使用Flutter構(gòu)建一個App。這里給大家建議是結(jié)合書中的內(nèi)容進行編碼實踐,現(xiàn)在我們就一起學習Flutter,相信它會給你帶來一種神奇的體驗。為了提高學習效率,作者提供在線答疑服務,網(wǎng)址//,郵箱r80hou@或加QQ群:169055795?;A篇包括了以下幾章:第1章Flutter簡介介紹Flutter的一些發(fā)展情況和概括性地總結(jié)Flutter的技術(shù)架構(gòu),讓你快速地了解Flutter,以及在不同的操作系統(tǒng)上安裝Flutter的運行環(huán)境和IDE。第2章深入理解Flutter基礎知識和小部件概念深入學習Flutter和Dart,以及如何使用Flutter構(gòu)建移動App。這一章會讓你了解到關(guān)于小部件的核心基礎知識,使用學到的小部件構(gòu)建第一個Flutter項目。第3章調(diào)試Flutter應用程序定位Flutter開發(fā)過程中不同類型的錯誤,學習不同的解決方式。第4章在不同設備上運行Flutter應用程序?qū)pp運行到iOS和Android模擬器及真實設備上。第5章列表ListView小部件和條件過濾深入學習ListView小部件,并根據(jù)條件渲染ListView中的內(nèi)容。第6章Flutter頁面導航學習如何構(gòu)建頁面導航,然后通過Flutter進行頁面切換,以及如何向前、向后傳遞數(shù)據(jù)。第7章處理用戶輸入學習使用基本表單小部件與用戶交互并保存用戶輸入的內(nèi)容。第8章深入學習Flutter小部件了解查找小部件的方式及配置小部件的方法。第9章Form表單學習以更好的方式處理用戶輸入,驗證輸入內(nèi)容并保存它們。通過本篇的學習,你可以了解到Flutter、Dart及小部件的概念;學會在macOS和Windows上搭建Flutter的環(huán)境;掌握調(diào)試技巧和竅門;理解基于堆棧的導航;處理并驗證用戶的輸入,從而搭建出具有基本功能的App。第1章Flutter簡介Flutter實際上是一個包含多種內(nèi)容的軟件包,你可以說它是用于創(chuàng)建移動2D應用程序的SDK軟件開發(fā)工具包。Flutter的軟件包中最重要的就是編程框架,框架使用Dart作為編程語言,通過本章的學習你將對Flutter的特性和開發(fā)技術(shù)有深入的了解。1.1什么是FlutterFlutter是一個基于Dart語言的框架,這個框架包含可以直接使用的類。這樣你就不必從頭開始編寫所有內(nèi)容。例如,F(xiàn)lutter附帶了大量的小部件,小部件實際上就是UI元素,例如按鈕、Tab頁、列表等,所以你不必編寫所有內(nèi)容,而是可以使用Flutter框架中的所有這些工具,添加自己的代碼和實現(xiàn)自己的邏輯,然后使用這些功能構(gòu)建原生應用程序。因此,只需使用一種語言Dart編寫代碼,你不必學習Java或Swift或其他任何東西。在熟悉了Flutter框架功能后,你可以根據(jù)不同平臺,編寫特定平臺的代碼,這也是我將在本書中介紹的內(nèi)容。Flutter不只是Dart編碼,它還是一組工具集合,允許你在設備上測試編寫的應用程序,具有很酷的功能,例如自動重新加載代碼中的任何內(nèi)容,以及在模擬器上運行應用程序,非常方便。Flutter還提供了構(gòu)建工具,以便將Dart代碼構(gòu)建打包,并上傳到AppleStore或Android應用商店中。Flutter會將Dart代碼編譯為本機代碼,因此,F(xiàn)lutter既是編程框架又是工具集合。為了更直觀地理解Flutter,我們看一下Flutter與Dart關(guān)系圖,如圖1.1所示,F(xiàn)lutter建立在Dart上。Dart是編程語言,然后Flutter提供了編程框架,它與Dart有很好的關(guān)聯(lián),或者在Dart上堆建。Flutter提供了許多實用功能和大量小部件,還包括構(gòu)建測試應用程序的SDK等工具,這就是Flutter。這是你將從頭開始學習的,我們將使用Flutter與Dart一起構(gòu)建原生移動應用程序并將它們發(fā)布到應用商店上。圖1.1Flutter與Dart關(guān)系圖1.2Flutter的架構(gòu)Flutter的架構(gòu)是什么樣的,以及它的核心概念是什么?使用Flutter構(gòu)建好App后,你會發(fā)現(xiàn)App只是一個小部件樹,可以將其視為應用程序中的UI元素,整個應用程序是一個UI元素,它包含子元素,例如導航欄;或者是一些文字,又或者是用戶的輸入框,也可以是一個按鈕。我們可以把這些小部件放到可視化的小部件中,例如行小部件、列小部件,然后對行和列進行排列組合的布局。Flutter是擁抱差異的,這意味著你可以使用一種編程語言編寫運行在iOS和Android平臺的應用。同時你也可以根據(jù)iOS和Android平臺的差異,去分別開發(fā)各自平臺的代碼,這就是Flutter很核心的一個概念。圖1.2一切都是小部件在Flutter中一切都是小部件,如圖1.2所示的就是開發(fā)完成后的一個頁面,在這個頁面中,使用了大量的小部件,但實際上比這里標示的還要多,例如按鈕是一個小部件,它上面的文字是另外一個小部件,整個頁面也是一個小部件,這樣就形成了一個小部件樹。應用是一個小部件,它包含了不同的頁面,然后每個頁面也是小部件,頁面中包含的內(nèi)容也是小部件,頁面和頁面之間還可以切換。下一個核心的問題是怎樣把Flutter中的Dart編碼轉(zhuǎn)換成原生應用的代碼。我們使用Dart語言編寫代碼,然后借助FlutterAPI編寫自己的小部件。那么怎樣才能編譯成iOS和Android的原生代碼呢?FlutterSDK幫助我們完成這項工作,你不必編寫任何原生的代碼,你只需要用Dart語言編寫,使用Flutter的功能,然后FlutterSDK就會完成代碼的編譯工作,以上就是Flutter提供給我們的全部功能,如圖1.3所示。下面我們就可以搭建開發(fā)環(huán)境,開發(fā)我們的第一個Flutter應用程序了,并把它運行到模擬器上。圖1.3Dart編碼轉(zhuǎn)換成原生應用的代碼1.3在macOS下安裝FlutterFlutter在macOS和Windows上的安裝步驟不同,這節(jié)講解如何在macOS上安裝Flutter。如果你是Windows用戶請?zhí)^1.3和1.4節(jié),同樣如果你是macOS用戶請?zhí)^1.5和1.6節(jié),下面我們看一下安裝過程。下載并安裝Flutter的步驟如下:首先訪問Flutter的官網(wǎng)https://flutter.dev/,瀏覽器將會顯示如圖1.4所示的頁面,單擊頁面右上方“Getstarted”,然后下載Flutter的穩(wěn)定版本。解壓文件到指定目錄,例如/flutter目錄下面,然后在終端運行vim~/.bash_profile命令,配置環(huán)境變量,如圖1.5所示。配置好變量后,在終端運行source./.bash_profile使配置生效,再運行flutterdoctor命令,這個命令檢查環(huán)境是否正確,并向終端窗口顯示報告。DartSDK與Flutter捆綁在一起,沒有必要單獨安裝Dart。請仔細檢查輸出以了解可能需要安裝的其他軟件或執(zhí)行的其他任務(以粗體顯示)。如果沒有安裝Xcode,需要安裝一下Xcode9.0或以上版本。同樣,如果沒有安裝AndroidStudio,也需要安裝最新版本的AndroidStudio。再運行flutterdoctor命令,如圖1.6所示,提示沒有可用的設備。圖1.4Flutter官方網(wǎng)站圖1.5配置Flutter環(huán)境變量運行open-aSimulator命令打開模擬器,然后通過命令創(chuàng)建我們的第一個FlutterApp。首先進入項目目錄,我的項目目錄是根目錄下的flutter-app,然后運行fluttercreatemy_app。Flutter會幫我們生成Flutter相關(guān)的文件,創(chuàng)建好后進入my_app目錄,運行flutterrun命令,這樣我們的第一個FlutterApp就創(chuàng)建好了,并成功運行到模擬器上了,如圖1.7所示。圖1.6檢查環(huán)境是否正確圖1.7FlutterApp運行在iOS模擬器上Flutter支持熱加載,完成啟動后,單擊R鍵進行熱加載。下面看一下如何將項目運行到Android的模擬器上,打開AndroidStudio,打開一個已有的項目,就是我們剛才生成的my_app。首先需要創(chuàng)建一個模擬器,單擊頁面上方的“Tools”按鈕,然后單擊“AVDManager”按鈕創(chuàng)建一個Android模擬器,如圖1.8所示。選擇這個模擬器,單擊頁面右側(cè)的“run”按鈕,把我們的FlutterApp運行到這個模擬器上。你可以使用AndroidStudio編寫代碼,也可以使用IntelliJIDEA,我們這里使用VisualStudioCode編寫。圖1.8創(chuàng)建一個Android模擬器1.4在macOS下安裝VisualStudioCode登錄網(wǎng)站/,如圖1.9所示,可以免費安裝VisualStudioCode,像大多數(shù)IDE一樣,這個網(wǎng)站會自動識別你的系統(tǒng),然后給你提供相應的下載內(nèi)容,下載后執(zhí)行這個文件,完成安裝程序。安裝非常簡單,沒什么特別之處,安裝完成后就可以運行它了。在啟動屏幕上選擇文件夾或文件,讓我們打開之前創(chuàng)建好的Flutter項目,如圖1.10所示,然后它就會呈現(xiàn)在IDE中。除此之外還需安裝一些插件,使IDE對Flutter的支持更友好。單擊屏幕上方的“View”按鈕選擇“Extension”,然后搜索Flutter找到官方的Flutter插件,單擊“Install”按鈕,如圖1.11所示,同時它會把Dart作為它的依賴也安裝上,安裝完成后,單擊“Reload”按鈕,重新加載一下你的IDE。還有一個可選的插件需要安裝,那就是MaterialIconTheme。這個插件跟Flutter沒有直接關(guān)系,但它會使圖標看起來更美觀。安裝完成后單擊“Explorer”按鈕,回到項目目錄,準備開始開發(fā)FlutterApp。在main.dart文件中找到_incrementCounter()方法把_counter++改成_counter=_counter+2,如圖1.12所示,這樣單擊一次按鈕就會加2。圖1.9下載用于macOS的VisualStudioCode圖1.10使用VisualStudioCode打開項目現(xiàn)在使用Flutter的熱加載功能,來到終端,按一下R鍵,F(xiàn)lutter就會執(zhí)行剛才的改動。如果App卡住了,可以按Shift+R,去重新構(gòu)建并加載?;氐侥M器中,看起來沒有什么變化,但是當我們單擊模擬器中的按鈕,會發(fā)現(xiàn)數(shù)字每次加2,從這就可以看出使用Flutter多神奇,以及使用它開發(fā)多容易,熱加載會貫穿于我們整個App開發(fā)過程中。書中還會介紹IDE的一些技巧,現(xiàn)在去看看怎樣在Windows系統(tǒng)中安裝Flutter,如果你是macOS用戶可以跳過下面兩節(jié)。圖1.11使用VisualStudioCode下載Flutter插件圖1.12編寫main.dart文件1.5在Windows下安裝Flutter下面看一下如何在Windows系統(tǒng)上安裝Flutter。首先訪問官網(wǎng)https://flutter.dev/,單擊頁面右上方的“Getstarted”按鈕,然后選擇“Windows”,如圖1.13所示。第一步看一下系統(tǒng)的要求,在Windows下安裝Flutter需要Windows7SPI或更高的版本,硬盤空間也很重要,不能低于400MB,還需要安裝兩個工具,如圖1.14所示。WindowsPowerShell5.0在Windows10里已經(jīng)預安裝了,如果是Windows的其他版本需自己安裝。另外一個工具是Git,可以在官網(wǎng)/download/winG下載并安裝,Git的安裝很簡單,確認好硬盤空間后,單擊“下一步”按鈕操作就可以了。圖1.13Flutter官方網(wǎng)站圖1.14需要安裝的工具現(xiàn)在我們就開始安裝Flutter,你可以從官網(wǎng)下載一個穩(wěn)定版本,如圖1.15所示。當你下載時,版本可能會與圖1.15所示的版本不同,但不管怎樣,你只要下載官網(wǎng)的穩(wěn)定版本就可以。圖1.15下載Flutter的穩(wěn)定版本下載完成后,把它解壓到一個目錄下,這個目錄不是你的App目錄,而是SDK目錄。SDK是軟件開發(fā)工具包,可以在系統(tǒng)上全局安裝,然后從系統(tǒng)不同目錄下使用它來創(chuàng)建Flutter項目,并使用這個項目,例如我們解壓到D:\Progams\flutter目錄下。這個目錄可以自己指定。下一步進入這個目錄,雙擊運行flutter_console.bat這個文件,它會彈出一個Flutter命令窗口,可以在這個窗口中運行Flutter命令,這里我們使用Windows自帶的命令提示符,在使用之前需要配置一下全局變量,目的是讓Windows能夠找到對應的路徑,如圖1.16所示。選擇控制面板并單擊“用戶”按鈕,下一步單擊“我的環(huán)境變量”按鈕,然后編輯環(huán)境變量,單擊“新建”按鈕,輸入安裝的Flutter目錄下的bin目錄,然后單擊“確定”按鈕。圖1.16配置環(huán)境變量關(guān)閉所有的命令行,打開一個新的命令行,輸入命令flutter,按下回車鍵。如果屏幕上顯示的內(nèi)容如圖1.17所示,說明環(huán)境變量配置成功了,就可以在命令行中輸入Flutter相關(guān)命令了,這樣Flutter就安裝好了。圖1.17運行命令flutter后顯示的內(nèi)容下一步安裝AndroidStudio,訪問網(wǎng)站/studio下載并安裝,下載前需要同意一些協(xié)議,下載完成后,執(zhí)行安裝,確認勾選了AndroidVirtualDevice這一項,如圖1.18所示。圖1.18勾選AndroidVirtualDevice選擇安裝的路徑,可以使用默認的安裝路徑,也可以自定義,再單擊“Next”按鈕,執(zhí)行安裝程序,安裝好后就可以啟動AndroidStudio了。首次啟動會彈出使用向?qū)?,提示你設置主題等個人偏好。選擇Android虛擬器這一步很重要,如圖1.19所示確認勾選了AndroidVirtualDevice,然后檢查AndroidSDK的位置,這里使用默認的配置,單擊“Next”按鈕,再單擊“Finish”按鈕。這里提示大家,這一步需要很長的時間進行加載,因為安裝過程中需要下載很多軟件包。圖1.19勾選Android虛擬器在命令提示符中輸入fluttercreatefirst_app來創(chuàng)建一個Flutter項目,項目名稱中只能使用下畫線,而不能使用空格和橫杠,然后按回車鍵,F(xiàn)lutter會自動創(chuàng)建一些配置文件。創(chuàng)建完成后,打開AndroidStudio,選擇一個存在的Android項目,就是剛才創(chuàng)建好的Flutter項目。打開一個模擬器,因為開發(fā)階段大部分功能是在模擬器上調(diào)試并開發(fā)的,然后再到真實的設備上測試。單擊屏幕上方的“Tools”按鈕,選擇“AVDManager”按鈕,單擊“+CreateVirtualDevice...”按鈕創(chuàng)建一個新的模擬器,如圖1.20所示。首先選擇一個設備,然后頁面會顯示創(chuàng)建向?qū)?。這里需要選擇模擬器的系統(tǒng),請選擇使用最新的版本,單擊“Next”按鈕。最后配置Graphics,選擇Hardware,如圖1.21所示。單擊“Finish”按鈕,這樣這個模擬器設備就創(chuàng)建好了。單擊運行圖標,如圖1.22所示,模擬器就顯示出來了。下一步需要在AndroidStudio中安裝缺少的依賴項和插件,單擊IDE右上方的“Installplugins”按鈕,如圖1.23所示,然后重啟。啟動好后IDE右下角會有一個提示,如圖1.24所示,建議安裝插件,單擊“Configureplugins”按鈕,會彈出Flutter插件,單擊“Accept”按鈕,同時也會自動安裝Dart插件,Android完成后需要再次重啟IDE?;氐矫钐崾痉翱冢\行命令flutterdoctor,命令提示符窗口會提示漏掉了哪些內(nèi)容。圖1.20創(chuàng)建一個新的模擬器圖1.21配置Graphics圖1.22啟動模擬器圖1.23安裝插件圖1.24配置插件回到AndroidStudio,單擊IDE右上角“?”運行按鈕,運行我們創(chuàng)建的這個Flutter項目,可以看到FlutterApp已經(jīng)運行到模擬器上了,單擊“浮動”按鈕,可以增加計數(shù)器,或者在項目的目錄下運行命令flutterrun來啟動。1.6在Windows下安裝VisualStudioCode我們使用VisualStudioCode,可通過網(wǎng)站/下載IDE,如圖1.25所示。這個IDE是免費的,并且支持Flutter的擴展,訪問網(wǎng)站,它會根據(jù)你的系統(tǒng)提供一個適合的下載版本。下載并安裝IDE,安裝步驟簡單,沒有什么特別需要說明的,安裝完成后就可以運行它了。圖1.25在Windows下下載安裝VisualStudioCode為了使這個IDE更好用,需要添加一些插件,單擊“Extension”圖標,如圖1.26所示。搜索Flutter插件,安裝官方的Flutter插件,Dart會隨這個插件一起安裝,安裝完成后,重啟IDE。圖1.26使用VisualStudioCode下載Flutter插件另外,還要安裝一個插件MaterialIconTheme,這個插件與Flutter安裝無關(guān),它只是會使IDE變得美觀。在項目目錄下找到main.dart文件,然后到incrementCounter()方法里,把_counter++改成_counter=_counter+2,如圖1.27所示。圖1.27編寫main.dart文件這樣每次單擊“浮動”按鈕就會加2。來到命令行窗口,不需要使用Ctrl+C鍵退出,只需要按R鍵進行熱加載就可以使改動生效,這意味著你不需要重新Build就可以修改你的App了。如果更新失敗或者模擬器卡住了,需要按Shift+R鍵重新Build才可以。接下來回到模擬器,單擊“加號浮動”按鈕,會看到計數(shù)器每次增加2而不是1,這是第一個小的改變,接下來我們將更深入地學習Flutter。1.7Flutter中的MaterialDesign體系MaterialDesign是谷歌創(chuàng)建的一個設計系統(tǒng),它看起來如圖1.28所示。Flutter使用了MaterialDesign。它不僅是一種樣式,還可以靈活地自定義樣式,例如可以改變顏色、位置或者包含其他小部件,這樣就可以設計出自己的小部件。MaterialDesign已經(jīng)植入到Flutter中了,F(xiàn)lutter也依賴MaterialDesign,所以FlutterApp實際上也是MaterialApp。Flutter正在積極地快速發(fā)展,現(xiàn)在已經(jīng)有了很多穩(wěn)定版本,隨著版本的更新,功能也隨之更新。關(guān)注官網(wǎng)可以及時了解它的變化。同時也會有更多的第三方軟件包添加到Flutter的生態(tài)系統(tǒng)中。Flutter也可能會存在Bug,如果遇到Bug,可以先定位Bug,確定到底哪里出問題了,然后關(guān)注這個問題。圖1.28MaterialDesign與Flutter的關(guān)系第2章深入理解Flutter基礎知識和小部件概念本章將深入學習Flutter和Dart及使用Flutter構(gòu)建移動App,還包括學習Flutter的核心基礎知識,主要是關(guān)于小部件的。不僅在理論上學習Flutter,還將使用Flutter構(gòu)建項目?,F(xiàn)在讓我們創(chuàng)建一個新的Flutter項目。2.1創(chuàng)建一個Flutter項目要創(chuàng)建一個Flutter項目,需要使用Flutter命令。首先需要配置Flutter的環(huán)境變量,在第1章已經(jīng)介紹了,然后在命令提示符中運行命令fluttercreate加上項目名稱,如圖2.1所示,如果項目名稱涉及多個單詞,請使用下畫線分隔,而不可以使用橫線和空格,單擊回車鍵。這將在當前運行命令的目錄下創(chuàng)建一個新的目錄,所以要確認好當前的目錄。新創(chuàng)建的目錄中包含了大量Flutter自動創(chuàng)建的Android和iOS相關(guān)文件。項目創(chuàng)建完成后,在日志中會顯示一些可以運行的命令?,F(xiàn)在不需要運行它們,而是使用IDE打開這個新創(chuàng)建的項目。圖2.1創(chuàng)建Flutter項目的命令這里使用VisualStudioCode打開這個項目,也可以使用AndroidStudio打開它。首先確保VisualStudioCode安裝了Flutter插件,然后打開VisualStudioCode集成的終端,在View下選擇Terminal,如圖2.2所示。圖2.2打開VisualStudioCode中的終端在當前項目目錄下的Terminal中運行Flutter命令,但是現(xiàn)在還啟動不了,因為運行Flutter項目需要一個模擬器或一個真實的設備。這里使用模擬器,所以讓我們快速啟動一個模擬器,打開AndroidStudio,單擊“Tools”按鈕,再單擊“AVDManager”按鈕,如圖2.3所示。圖2.3打開VisualStudioCode中的終端選擇一個設備,也可以創(chuàng)建一個新的設備,并單擊右側(cè)的“?”運行按鈕,如圖2.4所示。圖2.4啟動Android模擬器模擬器運行起來后,回到VisualStudioCode中,啟動Flutter項目,單擊“Debug”按鈕,選擇“StartDebugging”,或者“StartWithoutDebugging”,如圖2.5所示。圖2.5啟動Flutter項目此時模擬器有可能會提示選擇環(huán)境變量,只需選擇FlutterAndDart即可。構(gòu)建好Flutter項目后,IDE會發(fā)送給模擬器,如圖2.6所示。頂部有個控制面板,可以調(diào)試、重啟、退出、暫停項目。這個應用程序如圖2.6中模擬器所示,這是Flutter自帶的,而不是我們編寫的,下一節(jié)我們將重新編寫一個應用程序。圖2.6運行的Flutter項目2.2Flutter目錄結(jié)構(gòu)及main文件我們啟動并在模擬器上運行了Flutter項目,現(xiàn)在打開main.dart這個文件并刪除所有內(nèi)容,如圖2.7所示,從零開始學習如何編寫Flutter代碼。首先介紹一下圖2.7中左側(cè)的目錄和文件:.idea目錄是AndroidStudio中的文件不要刪除,也不需要了解其中的內(nèi)容;android和ios目錄非常重要,因為它們保存著本機的代碼,并且是應用構(gòu)建過程的重要部分,android和ios目錄中的內(nèi)容不經(jīng)常用到,后面的章節(jié)用到時再學習;lib目錄是編寫整個Flutter應用的地方,我們將在這個目錄下編寫Dart和Flutter代碼;test目錄下可以編寫自動化測試代碼。其他文件是基本的配置文件,例如.gitignore文件是版本控制文件,其他配置文件中包含SDK的配置信息,不需要編輯它們。pubspec.yaml文件是配置整個項目及其依賴的,這個文件是很重要的。后面章節(jié)會介紹添加第三方包,例如相機設備,會經(jīng)常修改這個文件中的某些配置,現(xiàn)在編寫我們應用程序的一些基礎代碼。main.dart文件是一個很重要的文件,不可以重新命名,因為Flutter構(gòu)建項目時會尋找main.dart這個文件,文件中包含一些特殊的方法來啟動整個App,其中有一個main()方法,在Flutter中創(chuàng)建方法,需要輸入一個名字例如main,這個方法比較特殊,App在啟動的時候會尋找這個main方法。其他的方法可以自己命名,然后輸入括號,在括號中可以指定任何參數(shù),然后在方法體中使用這些數(shù)據(jù),但是main()方法不接受任何參數(shù),方法體中執(zhí)行的代碼需要用大括號括起來。如果執(zhí)行某個方法,可以像如下代碼這樣寫。圖2.7Flutter項目中的main.dart

main();//調(diào)用main()方法

但是對于main()這個特殊的方法我們不能去調(diào)用它,F(xiàn)lutter會自動調(diào)用它,所以這就是我們必須要命名為main()并且把它放到main.dart中的原因?,F(xiàn)在可以啟動App,開始渲染用戶界面并運行到操作系統(tǒng)上,這可以通過Android和iOS來完成,但是要在屏幕上呈現(xiàn)一些內(nèi)容,需要在main()方法中做一些事情。例如將一個小部件附加到屏幕上,接下來講解什么是小部件。2.3Flutter中小部件的概念Flutter中一切都是小部件,小部件是構(gòu)造塊,UI組件。如果將一個Flutter應用運行到移動設備上,它通常由多個小部件組成。例如頂部的標題欄、導航欄、標題圖片、包含內(nèi)容的列表等,它們都是單獨的小部件,通常還包含其他小部件,如圖2.8所示。圖2.8中的列表含列表項作為子部件。頁面本身也是小部件,如圖2.8所示的scaffold小部件,甚至整個應用程序都包含在一個根小部件中。因此小部件實際上是UI組件,但它們不僅僅是視覺組件,還包含邏輯組件。例如,按鈕小部件不僅會顯示按鈕,還會定義單擊按鈕時會發(fā)生什么。構(gòu)建Flutter應用程序是通過創(chuàng)建UI,然后編寫UI的邏輯來實現(xiàn)的,例如選擇移動設備上的圖片并上傳到服務器上、從服務器上獲取數(shù)據(jù)并渲染到屏幕上等。圖2.8Flutter應用中的小部件我們可以將Flutter應用視為小部件的樹,一個根小部件包含整個應用程序,可能會有40個不同頁面的小部件作為子小部件,然后為子小部件嵌套其他小部件,如圖2.9所示。圖2.9Flutter中的小部件樹實際上我們建立了如圖2.9所示的一個小部件樹,我們可以使用Dart編程語言完成所有這些工作,讓我們看看如何創(chuàng)建這樣的小部件樹。2.4創(chuàng)建Flutter小部件現(xiàn)在App中沒有任何內(nèi)容,我們只寫了一個main()方法,將來它將會被調(diào)用,但是我們不知道在main()方法里執(zhí)行什么。上一節(jié)我們學習到整個Flutter應用都是由小部件組成的,所以我們應該寫一個小部件。首先創(chuàng)建根小部件,要實現(xiàn)它需要使用Dart語言的一個特性——類。你可能在其他的語言中聽說過這個概念,Dart是面向?qū)ο蟮木幊陶Z言,所以一切都是對象,一個對象就是一個簡單的數(shù)據(jù)結(jié)構(gòu),類允許為對象創(chuàng)建屬性和方法。Flutter提供了很多類供我們使用,但也可以創(chuàng)建自己的類。輸入class關(guān)鍵字后,可以輸入一個類名,類名以一個大寫字母開頭,然后輸入名字,代碼如下:

classMyapp//class關(guān)鍵字加上類名

這里將Myapp作為一個詞使用,也可以使用多個詞,每個詞以大寫字母開頭,代碼如下:

classMyApp//將MyApp作為多個詞來命名

類的名稱不能使用橫線、下畫線,這就是類。現(xiàn)在可以給這個類加一些特性,例如方法、變量,變量你可能從其他的語言中了解過,變量是簡單的、小的數(shù)據(jù)結(jié)構(gòu),例如name='tom'。但是,如果想把一個混合的數(shù)據(jù)賦值給name,需要把name指向一個對象?,F(xiàn)在我們想創(chuàng)建一個小部件,一個小部件是一個對象,這個對象是由類來定義的,但是我們自己創(chuàng)建的類,F(xiàn)lutter不認為它是一個小部件類,因為一個小部件需要某些特性,因此我們的類必須繼承其他的類,繼承使用extends這個關(guān)鍵字,允許繼承一個類,意味著當前類繼承了這個類的所有特性,然后你可以使用這些特性或者添加自己的特性。如果繼承了Flutter的類,F(xiàn)lutter便會知道它可以安全地使用這個類的對象,并在屏幕上繪制一些內(nèi)容。我們需要繼承的類來自Flutter框架,所以需要了解特性import。編寫代碼時需要使用FlutterSDK框架中的代碼,因此需要通過import關(guān)鍵字,引入需要的文件的路徑,從這些特性可看出Dart是一門模塊化的語言,同時也意味著可以將代碼切分成多個文件,下面引入Flutter包中的文件,代碼如下:

import'package:flutter/material.dart';//引入Flutter框架中的文件

我們通過package:加包名flutter,flutter包中包括很多的子包或者文件,可以通過/加文件名來定位文件,上述例子中引入了material.dart這個文件?,F(xiàn)在我們可以繼承這個文件中暴露的一些類。例如無狀態(tài)小部件StatelessWidget、有狀態(tài)的小部件StatefulWidget。因為我們引入了對應的文件,所以這里繼承StatelessWidget,代碼如下:

//Chapter02/02-04/lib/main.dart

classMyappextendsStatelessWidget{//繼承無狀態(tài)小部件

}

現(xiàn)在就可以把它作為一個小部件并顯示在屏幕上了。這里還有一個很重要的事情需要說明,將在下一節(jié)介紹。2.5小部件中的build方法現(xiàn)在Myapp類已經(jīng)繼承了StatelessWidget,因此Myapp是一個有效的小部件了,我們可以看到Myapp下面有一個橫線,如果把鼠標懸停在上面,會看見一些錯誤的提示信息,如圖2.10所示。圖2.10Myapp中錯誤的提示信息提示當前類中缺少build方法,所以輸入build()加上大括號,定義一個方法。但還是有下畫線,如圖2.11所示。圖2.11build方法提示的錯誤信息這里需要告訴Flutter,Myapp這個類創(chuàng)建的對象是一個小部件,需要顯示到屏幕上,也可以認為Flutter通過調(diào)用對象中的build()方法來顯示某些內(nèi)容,這就是要在創(chuàng)建小部件中添加build()方法的原因。build()方法實際上需要通過方法中的參數(shù)傳遞一些數(shù)據(jù),這些數(shù)據(jù)是Flutter傳遞的。因為Flutter會調(diào)用build()方法,build()方法需要一個參數(shù)context,context實際上是一個對象,包含應用的一些元信息,以及繪制小部件的位置。例如context中包含了應用的主題,目前可以先忽略它。現(xiàn)在我們在build()方法中添加一些內(nèi)容。build()方法需要返回內(nèi)容,所以需要使用return關(guān)鍵字。因為Flutter需要執(zhí)行build()方法來知道在屏幕上繪制什么,所以Flutter需要執(zhí)行build()方法返回的內(nèi)容,我們在方法體中添加return關(guān)鍵字,但現(xiàn)在的問題是需要在這里返回什么。這里有一個很重要的規(guī)則,在build()方法中,小部件總會返回另一個小部件,一直遞歸到Flutter附帶的小部件為止。這里可以使用Flutter附帶的MaterialApp小部件,它是一個很特殊的小部件,可以用來包裝整個App。App可以通過它來設置主題,也可以添加一個導航器,使應用在不同頁面間進行切換等。所以MaterialApp是核心的根小部件,在每個FlutterApp中都會用到它。在Myapp小部件中將MaterialApp返回,作為最頂級的小部件,代碼如下:MaterialApp小部件中可以配置一些內(nèi)容,并顯示在屏幕上?,F(xiàn)在模擬器上面沒有顯示任何內(nèi)容,所以需要給MaterialApp傳遞數(shù)據(jù),下一節(jié)來實現(xiàn)這個功能。2.6添加Scaffold頁面到目前為止,F(xiàn)lutter的內(nèi)容已經(jīng)涵蓋了很多方面,但是在模擬器的屏幕上還是什么都看不到,所以我們需要告訴MaterialApp需要做些什么,然后顯示到模擬器的屏幕上。我們可以給MaterialApp傳遞參數(shù)。之前在創(chuàng)建build()方法時需要一個參數(shù),同樣MaterialApp的構(gòu)造器也需要傳遞參數(shù),它接收命名的參數(shù),這意味需要添加一個名字,例如home。這個參數(shù)加上冒號然后加上傳遞的值,還有一種是位置參數(shù),例如build(context),這里的參數(shù)不需要名字,build()方法中傳遞的第一個參數(shù)會被認為是context。在Flutter中我們會經(jīng)常用到命名參數(shù)。現(xiàn)在我們需要給home這個參數(shù)傳遞一個值,home需要傳遞的實際上是小部件,它們會被繪制到屏幕上。這里你可以使用Scaffold,它是material包附帶的,Scaffold可以在App中創(chuàng)建一個頁面,默認是白色的背景,也可以修改這個背景顏色。Scaffold還可以添加標題欄等小部件。同樣需要在構(gòu)造器中傳遞數(shù)據(jù),其中一個參數(shù)叫appBar,輸入冒號,添加一個頂部的導航欄AppBar()小部件,現(xiàn)在同樣也需要配置AppBar來顯示內(nèi)容。其中一個參數(shù)為title。把鼠標懸停在AppBar上,會看到我們可以傳遞哪些參數(shù),你會發(fā)現(xiàn)title這個參數(shù)同樣會傳遞一個小部件。這里我會用到這個小部件鏈上的最后一個小部件Text,Text是一個需要傳遞String類型數(shù)據(jù)的小部件。Text是由位置參數(shù)創(chuàng)建的,所以只需要傳遞一個String類型的數(shù)據(jù),并放在參數(shù)的第一個位置,代碼如下:這樣Text小部件就可以獲取到數(shù)據(jù)了?,F(xiàn)在傳遞一個String類型的數(shù)據(jù),它將會被顯示出來。但是在模擬器的屏幕上還是什么都看不到,這是因為雖然我們創(chuàng)建了小部件,但沒有掛載到屏幕上。在main()方法中,沒有執(zhí)行任何內(nèi)容。main()方法中需要運行一個特殊的方法,也是material包附帶的,這個特殊方法是runApp()。runApp()方法需要傳遞一個參數(shù),這個參數(shù)必須是一個小部件。創(chuàng)建小部件Myapp,代碼如下:Myapp中包含了MaterialApp、Scaffold等??梢試L試使用熱加載運行模擬器,如果失敗了,需要退出,然后單擊“StartWithoutDebugging”來啟動。這就是當前我們的App,如圖2.12所示。圖2.12成功啟動Flutter應用可以看到AppBar和Scaffold的白色背景,以及包含這一切的MaterialApp的小部件。2.7深入學習Dart語法我們創(chuàng)建了一個非常簡單的Flutter應用,在main.dart文件中調(diào)用main()方法,然后調(diào)用runApp()方法,在runApp()方法中創(chuàng)建了一個我們自己的類的對象,實際上是調(diào)用Flutter的build()方法返回了一個小部件樹。我們用Dart語言編寫了以上內(nèi)容,例如導入語句、方法的語法、類等,這些都是用Dart編寫的。Dart實際上是一種強類型語言,意味著必須定義方法和變量的類型。這對開發(fā)者來說是有幫助的,因為如果你輸入一個錯誤的類型,IDE會有錯誤的提示信息,在構(gòu)建應用過程中也會被發(fā)現(xiàn)。build()方法返回了一個小部件,但是我們并沒有聲明返回類型,不過IDE也沒提示報錯。這是因為Dart語言實際上已經(jīng)根據(jù)MaterialApp小部件推測出會返回一個小部件。為了使這段代碼更清晰,我們需要在build()方法前面加Widget這個類型,意味著Widget是我們期望的返回類型。如果把return返回的內(nèi)容設置為'hello',IDE會給我們錯誤的提示信息,顯示返回類型錯誤。這樣當保存代碼的時候,代碼不能被重新編譯。所以在build()方法前,要改成返回一個小部件。代碼如下:添加返回類型可以避免出現(xiàn)錯誤。build()方法實際上是StatelessWidget中一個已經(jīng)定義的方法,我們可以在build()方法的參數(shù)前面加一個類型,使代碼更清晰,參數(shù)context的類型是BuildContext,BuildContext是material包中提供的另外一個類,代碼如下:這樣我們可以很清楚地知道context是BuildContext的類型,確保我們在使用時不會犯錯。對IDE來說也很好,在IDE中我們可以通過context加點來獲得提示和建議。我們也可以給main()方法加返回類型,main()方法沒有返回任何內(nèi)容,可以在前面加void類型,表示這個方法不會返回任何內(nèi)容,代碼如下:如果有返回值,IDE會提示報錯?,F(xiàn)在的代碼比之前更易讀了,所以強烈建議使用類型,類型是一個關(guān)鍵的特性,將在后面章節(jié)中經(jīng)常使用它。如果main()方法中只有一行代碼,有一個更簡單的寫法,代碼如下:build()方法實際上是StatelessWidget類中的方法,我們覆蓋了它,所以我們需要在這里加一個注解,代碼如下:添加@override注解不是必須的,@override可以告訴Dart和Flutter,我們有意重寫這個方法。加注解可以使代碼變得好理解?,F(xiàn)在代碼變得更清晰了,下一節(jié)我們給這個應用加些其他的內(nèi)容。2.8使用Card小部件和圖片現(xiàn)在應用中只有一個導航欄,Scaffold是用來創(chuàng)建頁面的,不僅可以在它上面創(chuàng)建AppBar,還可以添加其他參數(shù),把鼠標懸停在Scaffold上,會看到有一個參數(shù)body,如圖2.13所示。圖2.13Scaffold中的參數(shù)bodybody顯示在appBar的下面,它也需要傳遞一個小部件。在body:后面創(chuàng)建一個Flutter的小部件,也可以是自定義的小部件。自定義的小部件會形成Flutter附帶的小部件樹,但最終也會遞歸成Flutter附帶的小部件,這是因為只有Flutter附帶的小部件才能被轉(zhuǎn)化為原生的UI組件。在body里添加一個Card小部件,它也是flutter/material包中附帶的。Card中的內(nèi)容突出顯示,還略帶陰影效果。同樣它也需要傳遞一些參數(shù),其中一個重要的參數(shù)是child,child同樣也需要傳遞一個小部件。傳遞的小部件就是顯示在卡片上的內(nèi)容。我們在卡片上加圖片和圖片下面的標題這兩個元素,這里需要傳入另外一個小部件,它也是Flutter附帶的,即Column小部件。它同樣需要傳入?yún)?shù),其中一個參數(shù)叫children,和child不同,child只需傳一個小部件,children需要傳入多個小部件并上下排列。代碼如下:用<>括起來的寫法叫泛型,是數(shù)組的一個附加注解,使我們更清楚地知道這個數(shù)組只能包含小部件。[]括起來的是數(shù)組,可以傳入一組數(shù)據(jù)而不僅僅是一個數(shù)據(jù),例如Column、Card、AppBar、Text、Scaffold等。這里可以添加兩個小部件,以逗號分隔。一個是小部件Image,它也是包flutter/material附帶的;另一個是Text小部件,并傳入一個字符串'news1'。代碼如下:Image需要傳入一張圖片,在項目中創(chuàng)建一個目錄,命名為assets,用它來保存靜態(tài)資源。我們可以任意找一張圖片,并重命名為news1.jpg,然后把它拖放到assets這個目錄下。要顯示這張圖片,把它放到這個目錄下還不夠,我們需要在pubspec.yaml這個文件中配置訪問圖片的路徑。訪問的文件是assets下面的news1.jpg,如圖2.14所示。現(xiàn)在就可以在項目中使用這張圖片了。在main.dart中,可以使用Image小部件特別的構(gòu)造器來創(chuàng)建,Image小部件和括號之間加.asset,代碼如下:Image將加載已經(jīng)配置好的資源,參數(shù)是資源的路徑,類型是String。保存后,圖片將會被加載到App上,如圖2.15所示。圖片和圖片下面的標題分布在Card上面,占據(jù)了整個Card的寬和高,可以看到底部略帶陰影,但是我們希望構(gòu)建更多的內(nèi)容來形成小部件樹。接下來我們學習更多的核心小部件。圖2.14配置圖片路徑圖2.15圖片在App上顯示的效果2.9官方文檔及使用按鈕RaisedButtonFlutter官網(wǎng)上提供了很多內(nèi)容,用瀏覽器訪問flutter.dev,單擊“Getstarted”按鈕,如圖2.16所示。圖2.16Flutter官網(wǎng)在左側(cè)找到Widgetcatalog,單擊此鏈接,如圖2.17所示,可以看到Flutter自帶的所有小部件,而且它們被分類了。圖2.17Flutter中的小部件最重要的一個分類是Basics小部件,還有一個很重的分類是MaterialComponents小部件。MaterialComponents中包含AppBar、按鈕、輸入框、對話框、Card等。Basics小部件包含行、列、Container、Text、Image小部件,可以單擊小部件上的鏈接了解更多的內(nèi)容,例如小部件的構(gòu)造器,有的還有一些關(guān)于小部件的示例代碼。這些小部件看起來很多,不用擔心,我們將在本書中使用大量的小部件,一切都會變得更加清晰。知道怎么找到這些小部件了,現(xiàn)在可以繼續(xù)豐富App的功能了。當前的App只是顯示了Card,它占據(jù)了整個空間,這種效果并不是我們想要的?,F(xiàn)在修改它,添加更多的Card來展示一列Card。可以使用Column小部件,并給參數(shù)children傳值,然后把Card添加到數(shù)組[]中,代碼如下:重啟后會發(fā)現(xiàn)Card底部有一個邊了,如圖2.18所示。圖2.18Card顯示在列中現(xiàn)在可以加更多的Card了。同時需要在Card所在的列上面添加一個按鈕,可以添加RaisedButton小部件。它是一個帶有背景的按鈕,按鈕也需要配置一下,最重要的一個參數(shù)是child,它用來定義這個按鈕內(nèi)部顯示,可以傳入Text小部件,也可以傳入一個圖標。這里使用Text,Text的內(nèi)容是'添加資訊'。這里還需要傳入另外一個參數(shù)onPressed。值應該是一個方法,所以這里可以簡單定義一個空的方法,這個叫匿名方法,沒有名稱,只有參數(shù)列表和方法體?,F(xiàn)在都是空的,所以單擊按鈕不會執(zhí)行任何內(nèi)容。代碼如下:保存并重新加載,會發(fā)現(xiàn)屏幕頂部有一個按鈕可以單擊,但沒有任何反應。這個按鈕顯示得并不美觀,可以用Container小部件把它包裝起來。Container小部件中child參數(shù)的值就是按鈕。Container小部件有一個參數(shù)叫margin,表示Container與四周的外邊距。margin參數(shù)可以使用flutter/material包中的類EdgeInsets來賦值,這個類可以使用.all來調(diào)用構(gòu)造器,傳入一個浮點類型來定義四周邊界的距離,例如10.0像素。代碼如下:這個像素會自動適配設備的像素,現(xiàn)在我們可以看見按鈕周圍產(chǎn)生了邊距,但這個按鈕沒有任何功能,下一節(jié)讓我們將給這個按鈕加些功能!2.10創(chuàng)建StatefulWidget小部件現(xiàn)在單擊應用中的按鈕沒有任何反應,因為監(jiān)聽方法是空的,這個按鈕應該具有添加更多Card小部件的功能。那么怎樣再添加更多的Card呢?還有個問題是怎樣通過單擊按鈕來添加Card小部件呢?在按鈕的監(jiān)聽方法中,我們想改變一些數(shù)據(jù),然后動態(tài)地添加到卡片的列表中。我們需要管理一組數(shù)據(jù),例如從服務器獲得的數(shù)據(jù),后邊的章節(jié)將會介紹。首先確認build()方法什么時候被調(diào)用,build()方法會在應用第一次加載的時候被Flutter調(diào)用,或者當數(shù)據(jù)發(fā)生改變的時候也會被調(diào)用。可以在onPressed監(jiān)聽的方法中管理這組數(shù)據(jù),每次單擊按鈕時都要改變這組Card。StatelessWidget滿足不了這個需求,因為它是一個很簡單的小部件,StatelessWidget可以接收外部的數(shù)據(jù),然后簡單地調(diào)用build()方法,構(gòu)建一個小部件樹,它沒辦法管理內(nèi)部數(shù)據(jù)。如果內(nèi)部數(shù)據(jù)發(fā)生變化,也不能重新調(diào)用build()方法,因為StatelessWidget不能管理內(nèi)部數(shù)據(jù)。StatelessWidget只能在第一次被創(chuàng)建的時候調(diào)用build()方法,或者是接收到某些外部數(shù)據(jù)發(fā)生變化時,它會調(diào)用build()方法,所以現(xiàn)在不能使用StatelessWidget。我們需要使用StatefulWidget,State可以被簡單地理解為數(shù)據(jù),可以使用存儲在小部件中的數(shù)據(jù),同時也可以改變這些數(shù)據(jù)。當我們改成StatefulWidget后會有一個錯誤提示,顯示缺少方法createState(),如圖2.19所示。圖2.19缺少方法createState()createState()方法是必須要創(chuàng)建的,現(xiàn)在我們把這個類用大括號結(jié)束,代碼如下:在Myapp類中輸入createState()方法,VisualStudioCode會給提示,單擊回車鍵,代碼如下:createState()方法返回一個有狀態(tài)的小部件對象,<>是泛型,State這個類是屬于flutter/material包。這個狀態(tài)對象應該屬于Myapp。實際上需要創(chuàng)建兩個類來一起工作,createState()方法需要返回一個新的State對象,然后把這個對象配置給Myapp。還需要創(chuàng)建第二個類,可以寫成_MyappState,類名中的下畫線是一種約定,表示它不能被其他文件使用,只能在這個文件中使用。后面的內(nèi)容可能會使用多個文件,可以把Myapp引入到文件中并使用它,但是不可以使用_MyappState,然后輸入extends,因為State這個對象是屬于Flutter的,需要覆蓋build()方法,這是因為State這個類中也有build()方法?,F(xiàn)在我們只需要告訴Flutter,這個狀態(tài)類是屬于Myapp這個小部件的,需要在<>中加上Myapp,表明這個State屬于誰,這樣這兩個類的關(guān)系就創(chuàng)建起來了。Myapp需要返回_MyappState對象,所以把_MyappState()返回。代碼如下:類Myapp創(chuàng)建了一個State對象,這個對象包含build()方法,F(xiàn)lutter內(nèi)部會調(diào)用build()方法,這就是StatefulWidget的使用方法。那么怎么去使用StatefulWidget改變這組Card呢?下一節(jié)我們將詳細講解。2.11在StatefulWidget中管理數(shù)據(jù)我們已經(jīng)創(chuàng)建了一個StatefulWidget小部件,但問題是怎樣去管理和改變它內(nèi)部的數(shù)據(jù),可以用一個很簡單的方式去實現(xiàn)它。在_MyappState中添加一個屬性news,代碼如下:news是一個String類型的數(shù)組,因為Dart是強類型語言,所以需要在news的前面加類型List,這是Dart中的類型,表示數(shù)組。List可以添加泛型,這里是String泛型,表示這個數(shù)組中的內(nèi)容都是String類型的,這就是_MyappState的屬性。但數(shù)組是空的,下面我們給數(shù)組賦值,在中括號中輸入第一條資訊'first',代碼如下:現(xiàn)在需要把數(shù)組轉(zhuǎn)換到Card列表中并渲染到屏幕上,使用屬性時不可以使用this,可以直接引用它。這里需要調(diào)用數(shù)組的一個方法,在news后加點,有一個叫map()的方法,它允許將列表中的每一個元素轉(zhuǎn)換為新元素并將其返回。我們將在Column中的children參數(shù)列表返回一個新值,map中需要傳入一個方法參數(shù)來編寫轉(zhuǎn)化邏輯,方法將接收一個元素,這里你可以使用等號加箭頭來定義每個元素都發(fā)生了什么,代碼如下:我們需要根據(jù)元素創(chuàng)建Card,所以遍歷news中的每一個元素,然后把它轉(zhuǎn)化成Card。把Text小部件中的內(nèi)容直接替換成被遍歷的元素,因為它們都是String類型的數(shù)據(jù)。有一點需要注意,需要把被遍歷的元素element用小括號括起來,因為它是一個參數(shù),因為只有一句代碼,所以我們可以用=>這種方式編寫。雖然跨越了幾行代碼也是一句代碼。map()方法遍歷后返回的是一個Iterable類型的數(shù)據(jù),但是Column需要的是小部件數(shù)組,所以需要把map()方法遍歷后的結(jié)果轉(zhuǎn)化成List類型,我們可以通過調(diào)用tolist()方法來實現(xiàn)。下一節(jié)我們將學習使用按鈕添加更多的Card。2.12在StatefulWidget小部件中添加數(shù)據(jù)觸發(fā)按鈕的單擊事件能做一些事情,這里單擊按鈕需要改變news這個列表數(shù)據(jù)。當數(shù)據(jù)發(fā)生變化時,build()方法將會再次被執(zhí)行,此時它將使用的是更新后的news數(shù)組列表,進而更新Card并渲染到屏幕上。理論上,如果增加news數(shù)組列表中的數(shù)據(jù),將會獲得更多的Card,所以在按鈕單擊事件這里可以給news數(shù)組列表添加新的值。因為news數(shù)組列表是一個字符串列表,所以可以添加一個新的字符串'second',代碼如下:保存后,單擊按鈕卻什么都沒有發(fā)生。實際上我們改變了news,可以在這里打印出來,代碼如下:這只是一個debug方法,VisualStudioCode在底部的控制臺會打印出日志,單擊按鈕,控制臺已經(jīng)打印出來first和second了,如圖2.20所示。圖2.20打印news數(shù)組但是我們只看見一個Card,這是因為我們在這里改變了數(shù)據(jù),但是Flutter識別不出來,默認Flutter只關(guān)注屬性這里的數(shù)據(jù),當屬性數(shù)據(jù)發(fā)生變化時,必須告訴Flutter在StatefulWidget中已改變了屬性數(shù)據(jù)。要實現(xiàn)這樣的效果需要調(diào)用一個特殊的方法setState(),它是Flutter包提供的,需要接收一個方法參數(shù),在這個方法中編寫改變數(shù)據(jù)的方法,然后重新渲染App。這里添加news的數(shù)據(jù),代碼如下:保存一下,單擊按鈕會看到第二個卡片出現(xiàn)了。下一節(jié)我們再創(chuàng)建一個StatelessWidget,看看小部件之間如何交互。2.13把小部件拆分到單獨的文件中我們已經(jīng)學習了很多基礎的小部件,那么怎樣建立小部件之間的聯(lián)系呢?在編寫Flutter應用的過程中,需要經(jīng)常做的一件事就是拆分代碼并封裝。不可以把所有的代碼都放在一個根的小部件中,就像Myapp這個StatefulWidget小部件一樣。我們可以把應用拆分成多個細粒度的小部件,并把它們分發(fā)到多個文件中,這樣可以使每個小部件和文件都易讀,也容易維護。怎樣拆分呢?我們使用StatefulWidget來管理Card小部件和news數(shù)組,如果仔細觀察可以看到StatefulWidget是從這個列小部件開始渲染Card的,其他的小部件如MaterialApp、Scaffold、AppBar還有RaisedButton,它們都不會改變。RaisedButton按鈕是觸發(fā)改變狀態(tài)的部分,但也可以把這個按鈕拆分出來。首先我們把Card列表拆分出來。創(chuàng)建一個新的文件,命名為news.dart,可以隨意命名,但按照慣例文件名全部小寫,如果有多個單詞的話,用下畫線分隔。文件格式是dart。在這個文件中渲染資訊列表,可以把Card列表所在的列小部件復制到news.dart文件中。在news.dart文件中創(chuàng)建一個類News。現(xiàn)在需要擴展來自Flutter中的類,我們需要在每一個文件中添加import,代碼如下所示:

import'package:flutter/material.dart';//引入material包

因為每一個文件都是獨立的。在main.dart中引入的material包不會在這里生效,所以這里需要引入flutter/material包,然后創(chuàng)建一個小部件,并復制Column的邏輯放到這個小部件中,現(xiàn)在的問題是這里需要繼承一個有狀態(tài)的小部件還是無狀態(tài)的小部件呢?兩種方式都可以,但最好在這里使用無狀態(tài)的小部件,這列Card是需要改變的,為什么使用無狀態(tài)的小部件呢?因為數(shù)據(jù)的變化實際上是發(fā)生在其他的地方。News小部件接收一組news數(shù)據(jù),這組news數(shù)據(jù)可能被改變,但是它是在我們創(chuàng)建的News小部件之外被改變的。在News小部件中添加一個build()方法,使用VisualStudioCode的提示創(chuàng)建,代碼如下:把復制Column的邏輯放到return后面,代碼如下:IDE提示這個news不存在,怎樣把news數(shù)組傳到News這個小部件中呢?可以從外部傳入數(shù)據(jù),然后就可以在News小部件中使用傳入的數(shù)據(jù)了。我們可以通過構(gòu)造器來實現(xiàn),創(chuàng)建一個構(gòu)造器,輸入類名,小括號,大括號,代碼如下:構(gòu)造器在小部件創(chuàng)建的時候就會被調(diào)用,構(gòu)造器還有其他的特性,現(xiàn)在用到的一個特性是接收數(shù)據(jù)news數(shù)組,再可以給構(gòu)造器命名一個參數(shù)news,參數(shù)名可以任意命名,然后把傳進來的news存儲到News類的屬性中,所以需要在類中添加一個屬性,代碼如下:news屬性的類型是字符串型的數(shù)組,它不能改變,也沒有初始化?,F(xiàn)在把構(gòu)造器中的news存儲到這個屬性news當中。Dart語言提供了一個方便的快捷方式,在這里輸入this.news,會自動獲取傳入的參數(shù),并將其存儲在具有相同名稱的屬性中,這里需要在構(gòu)造器后面加分號,代碼如下:這樣就可以通過構(gòu)造器將數(shù)據(jù)傳遞到屬性中了。類News下面有一個波浪線,提示類中的所有內(nèi)容都是不可變的,如圖2.21所示。因為創(chuàng)建的是StatelessWidget,無論怎樣它都不能對變化做出反應,所以必須標注屬性不可以改變,在屬性前面加一個特殊的關(guān)鍵字final,代碼如下:圖2.21類News的提示信息這是Dart的一個特性,它告訴Flutter屬性news將永遠不會改變。從構(gòu)造器獲得的值初始化后屬性news將永遠不會改變。也可以不加這個final,加上它是為了更清楚這是一個僅從外部設置的值,如果有新的值從外部傳進來,它只是簡單地替換之前的值,只是替換,不會改變,然后再使用替換的這個值調(diào)用build()方法。2.14使用自定義小部件在main.dart文件中,已經(jīng)刪除了渲染Card的代碼,再刪除Container中的按鈕,并將其放入到自己創(chuàng)建的小部件中。創(chuàng)建一個新的文件news_manager.dart,用它管理News小部件。首先引入flutter/material包,創(chuàng)建類NewsManager繼承StatefulWidget,因為在NewsManager中需要管理news數(shù)據(jù)。StatefulWidget需要創(chuàng)建createState()方法,我們可以通過IDE的提示來創(chuàng)建,同時需要添加第二類_NewsManagerState繼承State,泛型連接到NewsManager,并且在_NewsManagerState中需要創(chuàng)建build()方法,在build()方法中需要返回的是按鈕和Card列表。代碼如下:現(xiàn)在缺少News小部件,需要在按鈕下面顯示News小部件。所以build()方法需要返回一個Column,并給參數(shù)children賦值,其中一個是包裝按鈕的小部件Container,另一個是在2.13節(jié)中的News小部件。現(xiàn)在不可用,因為還沒有引入,引入News小部件的代碼如下:點代表當前目錄,點點代表上一級目錄,這里只是在當前目錄,所以使用./news.dart。下面就可以使用News小部件了,News需要傳入一個參數(shù),所以把news數(shù)組傳入。代碼如下:通過setState改變news數(shù)據(jù),并再次調(diào)用build()方法渲染,同時也會渲染這里的News小部件,它被傳入了更新后的news數(shù)組列表,這將導致在News小部件中再次調(diào)用build()方法,這就是我們的NewsManager小部件。下面在main.dart文件中使用NewsManager小部件。在main.dart中我們不需要處理任何狀態(tài),所以可以把StatefulWidget改成StatelessWidget,刪除createState()方法,只需要覆蓋build()方法,body中不再是一個Column,而是NewsManager小部件,所以引入news_manager.dart,代碼如下:創(chuàng)建一個NewsManager小部件對象,代碼如下:現(xiàn)在應用代碼的結(jié)構(gòu)更清晰,包含多個文件,多個小部件,并且小部件可以復用,也使代碼更容易管理,因為每一個文件的內(nèi)容都不多,而且容易理解。2.15給StatefulWidget傳

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論