8天讓iOS開發者上手Flutter之三

franky發表於2021-07-21

搭建專案主框架

新建微信聊天,通訊錄,發現,我的四個檔案

上一篇文章最後我們已經將APP的TabBar和四個對應的子檢視搭建好了,但是每一個子檢視裡面肯定會有大量的程式碼,全部放到rootPage檔案裡面肯定是不合理的。所以我們為每個子檢視建立單獨的檔案,並將程式碼分散到每個檔案中。 image.png 比如聊天頁面,返回自己的Scaffold: image.png

現在我們點選切換一下tabBar的item,發現會有一些高亮的顏色,以及一個水波紋效果,這些都是MaterialApp類的theme提供的。如果想去掉這些效果,要來到main.dart檔案,設定以下兩個屬性: image.png

仔細檢視點選item的時候,文字被放大了。這個是bottomNavigationBar的屬性selectedFontSize決定的,將它設定為12.0之後,就不會變大了,在rootPage.dart檔案裡面: image.png

本地資原始檔

配置Android的啟動圖和應用圖示

Android和iOS的資原始檔,比如APP的圖示,啟動圖,需要到相應的專案檔案裡面去配置。我們大家都是iOS開發者了,這裡就只說一下Android的圖示和啟動圖如何配置。有需要圖片資源的同學可以前往下載 image.png

在安卓模擬器上執行起來之後,會發現安卓的標題不是在中間 Screenshot_1626706998.png
這裡可以通過AppBar的一個屬性,來調整讓它變成中間顯示 image.png

配置公共的資源

如果是兩端都需要的資源,比如我們APP的微信,通訊錄,發現和我的圖示。需要在當前flutter專案中配置了。 image.png pubspec.yaml檔案是我們flutter專案的配置檔案。檔案內assets和下面的幾行表示需要的圖片路徑,可以在flutter專案的根目錄下建立一個images的目錄,裡面存放所有當前flutter需要用的圖片。然後還需要手動匯入一張一張圖片...這點就比較噁心人了...更噁心人的是,這個yaml檔案的格式,包括位置都不能錯,比如剛剛放開註釋的時候,如果你使用的是command + /快捷鍵,那麼你就得好好挪動下位置了,位置不對編譯不通過。 image.png

實現發現頁

8天讓iOS開發者上手Flutter之三

設定APP啟動預設展示發現頁面

這個方便我們開發除錯這個發現頁面,我們開發原生APP的時候也經常會這麼幹。直接將rootPage.dart裡的_currentIndex設定為2就OK了,這個不用多說 image.png

配置導航條

微信的導航條顏色是灰色的。然後在安卓上這個導航條標題預設在左側,這裡也需要設定一下在中間。然後標題的顏色也不是白色,改為黑色。然後導航條和下面的body有一條黑線,可以通過設定elevation的值來控制。 image.png

8天讓iOS開發者上手Flutter之三

自定義發現cell

新建一個pages檔案,將所有頁面檔案都放到裡面。然後在新建一個discover_cell準備實現自定義的cell。按道理來說一個cell應該是需要更新UI的所以應該是有狀態的,但是現在我們是練手過程,可以先用一個無狀態的cell。 image.png 接下來就是實現這個自定義cell(discover_cell)的程式碼了;首先觀察微信的發現頁的cell,左側有一個圖示,和一個標題,這兩個是必須要有的,不然無法構成一個完整的cell,然後是右側有些cell會有子圖示和子標題,還有一個右箭頭,這個是每個cell都存在的。根據以上這些資訊,我們就可以定義出discover_cell應該要有的一些屬性了。如下:
title 左側的標題,必傳引數
imageName 左側的圖示,必傳引數
subTitle 右側的標題,非必傳引數,也叫可選引數
subImageName 右側的圖示,可選引數
image.png 如圖所示,宣告瞭這四個屬性之後,給出了紅色的報錯,可以將游標移到報錯的紅色字母任意處,按住option + 回車就可以彈出右側的選擇選單,第一個選項應該是新版本加的,俺也不是很清楚如何使用,網上資料很少,推薦去查詢官方文件了。我這裡就懶的去查了,因為我們要選擇的是第二個選線Create constructor for final fields建立構造方法。細心的同學會發現subTitle,subImageName的型別是String?這個型別後面跟了個問號,就是代表可選引數的意思,這裡跟iOS的Swift倒是十分相似。

選擇建立構造方法之後,系統會自動生成一行程式碼,但是這一行程式碼很長而且它不換行,非常難看。這裡有個小技巧,在生成的程式碼最後一個屬性後面加上一個,號然後再按option + command + L重新格式化程式碼,就會自動換行了。 image.png

換行之後發現,兩個必傳引數報錯,還是老辦法,游標移動到報錯的地方,按住option + 回車就會給出提示,意思我們要給必傳引數加上required關鍵字。這樣屬性的定義就算完成了。 image.png

屬性定義完了之後就是實現build方法搭建介面了。佈局介面的方式有很多,可以使用Row來佈局,也可以使用Stack加Positioned佈局,不管什麼方式能實現介面效果都可以。我這使用Row佈局。程式碼如下: image.png 最外層使用一個Container包裝一個Row,然後Row裡面再包含兩個Container包著的Row分別代表左右兩邊子檢視。這樣看上去應該還算蠻清晰明瞭的。左側部分的圖示和標題是必傳引數,沒啥好說的。右側由於子標題和子圖示都不一定存在,所以需要做一些處理,Text控制元件如果沒有子標題可以顯示空字串‘’,這個比較好解決。而子圖示不能說給一張空圖片,所以需要根據subImageName是否為空來顯示不同的控制元件,如果有就顯示Image,如果沒有就顯示一個Container佔位。最右側的箭頭圖示是每個cell都存在的就沒啥好說的了。自定義discover_cell的程式碼就算完成了,下一步完善我們的發現頁面

完善發現頁面

cell寫好之後,完善發現頁面就簡單多了。這裡使用最簡單的方式來實現,就是直接拼接每個子cell的方式。 image.png flutter裡面的ListView並不像iOS中的UITableView那樣分組和行。ListView只有行,自行合併幾個行組成一組,組與組之間使用一個SizedBox隔開,行與行之間使用Row(因為分割線左側是白色的,右側是灰色的,所以需要組合兩個Container)隔開。

其中購物哪一行cell右側的子標題和子圖示沒有設定字型大小和圖示大小,所以顯示可能會有點問題,回到cell裡面設定一下就好了。 image.png

實現點選cell切換到新頁面

讓cell能夠響應點選事件GestureDetector

flutter提供了一個GestureDetector類用來檢測手勢,它有一個child屬性,可以放我們的UI程式碼。它還能響應各種手勢,在不同的屬性裡面處理,比如我們點選cell就是onTap屬性。除了onTap之外,還有onTapDown,onTapCancel。其中onTapCancel是觸控之後離開了,onTapDown是按下就會被呼叫,onTap是按下去並鬆開之後呼叫。實現如下程式碼之後,自己試試就能明白其中差別了。 image.png

實現頁面之間跳轉

點選發現cell之後,需要跳轉它對應的詳情頁面,就需要一個詳情頁。可以新建一個discover_child_page.dart檔案,再去補充裡面的頁面程式碼。也可以從現有的一些空白檔案中複製一份,比如mine_page.dart檔案,它裡面就只有基本的我的頁面程式碼,只需少量修改程式碼就可以使用。不論使用哪種方式,新建discover_child_page.dart完成後,頁面程式碼如下: image.png 這個詳情頁的一些屬性,應該是需要從外面傳入的,比如title。於是定義一個title屬性。 image.png 然後在當前頁面展示我們的title,之前都是在StatelessWidget裡面使用我們的屬性,那在StatefulWidget裡面我們怎麼使用屬性呢?屬性前面加上widget. image.png 到這裡發現詳情頁就算差不多完成了。

回到cell裡面的點選方法,實現點選跳轉。這裡和iOS有點類似的地方就是同樣是使用一個導航控制器類。flutter也是使用一個名字叫導航的類Navigator。呼叫以下方法。 Navigator.of(context).push() push()的引數需要一個Route型別,這裡使用MaterialPageRoute類,MaterialPageRoute的構造方法返回一個Widget,這個返回的Widget就是我們需要跳轉到的頁面。程式碼如下: image.png 前面講過的,在flutter中,如果函式體的程式碼只有一句的話,可以使用=>的形式,於是上面可以簡寫成這樣: image.png

實現有狀態的discover_cell

修改discover_cell為StatefulWidget

原生的微信APP在點選cell的時候,會有一個灰色的背景,在鬆開的時候會變回最初的顏色。現在來實現這個效果。所以我們的discover_cell需要從StatelessWidget改為StatefulWidget。先將build方法縮起來,快捷鍵command加-號,0右邊那個減號。 image.png 然後先將bulid方法覆蓋,再將屬性和構造方法覆蓋。最後刪除原有的StatelessWidget類。這時候build方法裡面會爆一個錯誤,原因是_DiscoverCellState類裡面拿不到DiscoverCell的屬性,所以我們在屬性前面加上widget.就好了。

實現點選變灰需求

我們前面說過了onTap方法,onTapDown方法,onTapCancel方法的呼叫時機。實現這個需求就在這三個方法裡面更新狀態就好了。程式碼如下: image.png

相關文章