iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 7
3
Mobile Development

Flutter---Google推出的跨平台框架,Android、iOS一起搞定系列 第 7

【Flutter基礎概念與實作】 Day7–Flutter Basic Widgets

  • 分享至 

  • xImage
  •  

今天我們就從Basic Widget開始介紹。

Flutter官網列舉的Basic Widget共有11個,不過在這我只會提到Appbar、Column、Row、Container、Icon、Image以及Scaffold,接下來就一一來跟大家介紹他們的用途以及用法。
每一個widget我都會附上簡單的例子在Github上,大家可以直接複製程式碼來練習。


Appbar

先來看一個簡單的Demo


Appbar就是介面上方藍色的區域
可以把它細分成4個部分,其實還有一個部分是彈性的空間。

  • leading:通常就是放Logo的地方,你可以選擇單純的Icon或是IconButton
  • title:痾..就是個標題
  • actions:可以放常用的IconButton,例如搜尋、購物車按鈕之類的
  • bottom:可以用來放TabBar,也就是點選會轉換畫面的按鈕,範例中的笑臉和哭臉。

AppBar程式碼網址
※這個例子中我有使用到font_awesome這個套件提供的icon,在使用前麻煩到pubspec.yaml的dependencies處加上font_awesome_flutter: any,並在Terminal輸入或是上方點選Packages get指令來下載套件。


Column and Row

因為這兩個的功能完全一樣,它們只差在一個是水平一個是垂直而已,所以就一起介紹囉。

如果你之前有接觸過Android的開發,應該有使用過LinearLayout的經驗。
假如你的介面設計很複雜或是要求排版整齊,就會使用到多層的LinearLayout來排版(當然現在的ConstraintLayout是非常方便的,只是我在做大學專題時就傻傻全用LinearLayout排版,導致整個App卡到爆)。其實在Android裡是不建議使用多層LinearLayout,因為會嚴重影響到效能表現。

但在Flutter則是完全不同的情況,Flutter反而建議你用巢狀的Column或是Row來排版,對效能完全不會有影響。


簡單的用兩個例子來說明
Column用作垂直布局,例子中使用7個Text widget,分別放ptt各版標題。
Row用作水平布局,例子中是模擬ListView中的ListTile Widget

Column和Row比較常用的屬性是mainAxisAlignment用來設定內容物在主軸的對齊方式。
有以下幾種可以選擇,效果我想看圖應該很明顯就不再介紹了。


Column程式碼網址
Row程式碼網址
※ 如果你在練習時試著調大字體或是放更多的widget,可能會遇到下圖的狀況(螢幕上有黃黑條紋),這是Flutter在警告你的widget超出螢幕範圍,這種問題可以使用Expand或是Flexible調整。我在Row的程式碼中也有使用到Expand來調整文字。


Container

Container是一個容器,你可以設定它的長寬、背景顏色、邊界距離,甚至還可以讓它變形。

下方這個範例的介面是由外層青色Container包一個橘色Container,而橘色Container再包一個Text widget所組成。
並且在青色Container我設定了上下左右各50的padding(這樣才看的到青色部分)。
https://ithelp.ithome.com.tw/upload/images/20190916/201195500O4w1KcMen.png
接著來看變形的效果是如何,我讓青色Container的Z軸偏移0.1,橘色Container則是偏移-0.2,這樣看起來是不是很有設計感呀。

Container程式碼網址


Icon

在前面的範例中已經有使用到icon這個元件,用法也相當的簡單。這裡想要提的是雖然Flutter本身已經內建了許多不錯的icon了(點這裡查看所有icon。)
你也可以使用font_awesome這個套件提供的icon,它提供更多的選擇和類型,安裝方法可以參考前面Appbar備註的地方。


Image

圖片是App中不可或缺一部分,許多內容都要圖片來點綴不然會很單調,好在Flutter提供的Image Widget操作超級簡單,無論是載入本地端資料或是網路上圖片都只要一行程式碼就可以搞定。
下面示範三種載入圖片方式

// 載入網路資源,輸入圖片網址App就會自動去下載並載入
Image.network('https://titangene.github.io/images/cover/flutter.jpg')

// 一樣是從網路下載圖片,不過在下載好後會用淡入的動畫呈現
// 其中的kTransparentImage是transparent_image套件提供的透明圖片
// 需要在pubspec.yaml加上transparent_image: ^1.0.0來安裝套件
FadeInImage.memoryNetwork(
                 placeholder: kTransparentImage,
                 image:'https://titangene.github.io/images/cover/flutter.jpg')

// 一樣是淡入的效果,但在載入前會先用本地端圖片呈現(也可使用gif圖檔喔)
FadeInImage.assetNetwork(
                 placeholder: 'assets/waiting.gif',
                 image:'https://titangene.github.io/images/cover/flutter.jpg')


引入本地端圖片步驟:
a. 在project內新增「assets」資料夾,或任何你喜歡的名字都可
b. 到pubspec.yaml最下方flutter處添加

assets:
    -assets/   <-你的資料夾名稱
    //表示要引入assets資料夾內所有媒體資源

c. 即可使用assets內資源,例如在assets資料夾內有cute_cat.png檔案,就可以在程式中使用Image.assets('assets/cute_cat.png')引入圖片。


Image程式碼網址


Scaffold

還記得昨天說Scaffold是非常方便的widget嗎,今天就來看看它除了Appbar之外還有哪些東西可以使用。

  • Drawer:
    Drawer平常是隱藏在畫面的左側,當滑動螢幕時才會顯現出來
    我們可以用一個ListView來放側邊要呈現的項目,在使用者點擊項目或是空白處Drawer會在收回。

  • BottomNavigationBar
    NavigationBar就是在app最下方的導航列,你可以根據需求來更換頁面內容,而且還可以設定Icon被選擇後的變化(大小、顏色等等)。

  • SnackBar
    當使用者觸發某些動作或是系統完成某些事情,你想要提醒使用者,就可以使用SnackBar在畫面下方彈出訊息。


Drawer程式碼網址
NavigationBar程式碼網址
SnackBar程式碼網址


今日總結

今天介紹了幾個常見好用的基礎元件,並提供簡單的程式碼讓大家體會一下實際運作的狀況,由於時間的關係沒能解釋程式碼的細節,不過大家有任何問題都歡迎在下方留言,我會盡我所能地為你解答。

在這推薦Flutter官方的影片,他們用1分鐘的時間快速介紹每一個widget的用途,可以在閒暇時間認識到其他的widget。
其中有許多widget的效果都超讚的,快去挖寶吧。

明天我們來認識Dart Pub這個網站,看看Flutter到底有哪些好用方便的套件可以來讓我們使用。


上一篇
【Flutter基礎概念與實作】 Day6–Flutter Hello World!
下一篇
【Flutter基礎概念與實作】 Day8–Package引用與管理
系列文
Flutter---Google推出的跨平台框架,Android、iOS一起搞定30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
0
angel33er
iT邦新手 5 級 ‧ 2020-11-13 11:57:57

您好~執行Image程式碼網址時會出現錯誤,不好意思還不太會除錯,請問這錯誤代表什麼呢?

https://ithelp.ithome.com.tw/upload/images/20201113/20132508XojSfAcaHc.jpg

在程式碼有提到唷, 要下載「transparent_image」套件

// 一樣是從網路下載圖片,不過在下載好後會用淡入的動畫呈現
// 其中的kTransparentImage是transparent_image套件提供的透明圖片
// 需要在pubspec.yaml加上transparent_image: ^1.0.0來安裝套件
angel33er iT邦新手 5 級 ‧ 2020-11-13 13:29:05 檢舉

好的,有跑出來了~謝謝!

0

您好,想請問有關以下這段程式碼

class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);

final String title;

@override
_MyHomePageState createState() => _MyHomePageState();
}

其中MyHomePage(Key key, this.title)這邊
參數的地方我一定要寫成(Key? key,required this.title)才能正常執行,可以請問是為什麼嗎

To LittleRobot_we_like_IT,

  1. 針對 MyHomePage(Key? key,required this.title)中的Key?部分。Key?代表key的型態為nullable Key (i.e.可以是Key型態或null)。

2.針對 MyHomePage(Key? key,required this.title)中的required this.title部分。required這個keyword(關鍵字)告訴編譯器在呼叫MyHomePage function時,一定要指定title這個引數的值,否則會出現編譯錯誤。

詳見:
named parameter of function in Dart (Dart's official docs)

0
Code Lover
iT邦新手 5 級 ‧ 2024-12-12 19:55:53

程式碼修正

前言

To 原作者 bju0ulhi0511,
因為新版本Dart的關係導致直接複製您提供的AppBar.dart至main.dart會出現編譯錯誤。
compiler error at line 21 in main.dart底下的圖片(名為AppBar.dart (obselete code).png)

目前修正好的程式碼放在newer code of AppBar.dart
底下的new code (issue fixed)/AppBar.dart檔案裡面。

對原作者 bju0ulhi0511想說的話

若您看到這則留言,麻煩您改一下您的程式碼,以免人家複製您的程式碼後出現編譯錯誤,因而可能導致該人花了許多時間在處理該編譯錯誤上。

P.S.還好我只約一分鐘就解決該編譯錯誤。

程式碼錯誤

compiler報的錯誤

error: The parameter 'key' can't have a value of 'null' because of its type, but the implicit default value is 'null'. (missing_default_value_for_parameter at [testproject1] lib\main.dart:21)
error: The parameter 'title' can't have a value of 'null' because of its type, but the implicit default value is 'null'. (missing_default_value_for_parameter at [testproject1] lib\main.dart:21)

錯誤原因

  1. key不可以為null但因為沒有指定key預設值,key的預設值為null,互相矛盾。(在Dart新版中,若不指定named parameter的預設值,則該named parameter的預設值為null。詳見:named parameter of function (Dart's official docs))
    2.同理。 title不可以為null但因為沒有指定title預設值,title的預設值為null,互相矛盾。

解決方法

1.設定key的型態為Key?(pronounced as nullable Key),進而允許key可以為null。
2.同理。設定title的型態為String?(pronounced as nullable String),進而允許title可以為null。

更改後的程式碼

MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

改為

MyHomePage({Key? key, this.title}) : super(key: key);

  final String? title;

完整的程式碼

完整的程式碼,詳見newer code of AppBar.dart
底下的new code (issue fixed)/AppBar.dart檔案裡面。

謝謝你的反饋,已更新github程式碼

我要留言

立即登入留言