概覽

#

Flutter 版面配置機制的核心就是元件(Widgets)。 在 Flutter 中,幾乎所有東西都是元件(Widget)—甚至 版面配置模型本身也是元件(Widget)。你在 Flutter 應用程式中看到的 圖片、圖示和文字,都是元件(Widget)。 但你看不到的東西也是元件(Widget), 像是用來排列、限制和對齊可見元件(Widget)的 行(row)、列(column)和網格(grid)。 你可以透過組合元件(Widgets)來建立更複雜的元件(Widgets), 進而完成版面配置。

概念範例

#

在以下範例中,第一張螢幕截圖顯示了三個帶有標籤的圖示, 而第二張螢幕截圖則包含了行與列的視覺化版面配置。 在第二張螢幕截圖中,debugPaintSizeEnabled 被設為 true, 讓你可以看到版面配置的視覺化效果。

Sample layout
Sample layout with visual debugging

以下是前述範例的元件樹(widget tree)圖示:

Node tree

大部分內容應該如你所預期,但你可能會對那些(粉紅色顯示的)容器感到好奇。Container 是一個元件(Widget)類別, 它允許你自訂其子元件(child widget)。當你想要為子元件加入 內距(padding)、外距(margin)、邊框(border)或背景顏色等效果時, 就可以使用 Container

每個 Text 元件都被放在 Container 中,以加入外距。整個 Row 也被放在 Container 中,以在該行周圍加入內距。

其餘的 UI 則由屬性控制。 你可以透過 Iconcolor 屬性來設定顏色。 使用 Text.style 屬性可以設定字型、顏色、字重等。 列(columns)與行(rows)則有屬性可讓你指定其子元件 如何垂直或水平對齊,以及子元件應該佔用多少空間。

排版單一元件(Widget)

#

在 Flutter 中,如何排版一個單一元件(Widget)? 本節將示範如何建立並顯示一個簡單的元件(Widget), 同時也會展示一個簡單 Hello World 應用程式的完整程式碼。

在 Flutter 中,只需幾個步驟即可將文字、圖示或圖片顯示在螢幕上。

1. 選擇一個版面配置元件(Layout Widget)

#

你可以根據想要如何對齊或限制可見元件(Widget), 從多種版面配置元件(Layout widgets)中選擇, 因為這些特性通常會傳遞給其所包含的元件。

例如,你可以使用 Center 版面配置元件(Layout Widget), 將可見元件(Widget)在水平與垂直方向上置中顯示:

dart
Center(
  // Content to be centered here.
)

2. 建立可見元件 (Widget)

#

為你的應用程式選擇一個可見元件 (Widget)來承載可見元素,例如文字圖片圖示

例如,你可以使用Text元件來顯示一些文字:

dart
Text('Hello World')

3. 將可見元件 (Widget) 加入版面配置元件 (Layout Widget)

#

所有版面配置元件 (Layout widgets) 都有以下其中之一:

  • 如果只接收單一子元件,則有 child 屬性,例如 CenterContainer
  • 如果接收元件清單,則有 children 屬性,例如 RowColumnListViewStack

Text 元件加入 Center 元件中:

dart
const Center(
  child: Text('Hello World'),
),

4. 將版面配置元件 (Layout Widget) 加入頁面

#

一個 Flutter 應用程式本身就是一個元件(Widget),而大多數元件都有一個 build() 方法。在應用程式的 build() 方法中實例化並回傳一個元件,便會顯示該元件。

對於一般應用程式,你可以將 Container 元件(Widget)加入應用程式的 build() 方法中:

dart
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: const BoxDecoration(color: Colors.white),
      child: const Center(
        child: Text(
          'Hello World',
          textDirection: TextDirection.ltr,
          style: TextStyle(fontSize: 32, color: Colors.black87),
        ),
      ),
    );
  }
}

預設情況下,一般應用程式(general app)不會包含AppBar、標題或背景顏色。如果你希望在一般應用程式中加入這些功能,則需要自行實作。本範例應用程式將背景顏色設為白色,文字設為深灰色,以模仿 Material 應用程式的風格。

對於Material應用程式,你可以使用Scaffold元件(Widget);它會提供預設橫幅、背景顏色,並且有 API 可用於新增抽屜(drawer)、訊息條(snack bar)以及底部彈窗(bottom sheet)。接著,你可以將Center元件直接加到body屬性,作為首頁內容。

dart
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    const String appTitle = 'Flutter layout demo';
    return MaterialApp(
      title: appTitle,
      home: Scaffold(
        appBar: AppBar(title: const Text(appTitle)),
        body: const Center(
          child: Text('Hello World'),
        ),
      ),
    );
  }
}

若要建立 Cupertino 應用程式,請使用 CupertinoAppCupertinoPageScaffold 元件(Widgets)。

Material 不同,這裡不會自動提供預設的橫幅或背景顏色,你需要自行設定。

  • 若要設定預設顏色,請將已設定的 CupertinoThemeData 傳入應用程式的 theme 屬性。

  • 若要在應用程式頂部加入 iOS 風格的導覽列,請在 scaffold 的 navigationBar 屬性中加入 CupertinoNavigationBar 元件。你可以使用 CupertinoColors 提供的顏色來設定元件,使其符合 iOS 設計風格。

  • 若要配置應用程式的主體內容,請將 scaffold 的 child 屬性設為你想要的元件,例如 CenterColumn

想了解還有哪些 UI 元件可以加入,請參考 Cupertino 函式庫

dart
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const CupertinoApp(
      title: 'Flutter layout demo',
      theme: CupertinoThemeData(
        brightness: Brightness.light,
        primaryColor: CupertinoColors.systemBlue,
      ),
      home: CupertinoPageScaffold(
        navigationBar: CupertinoNavigationBar(
          backgroundColor: CupertinoColors.systemGrey,
          middle: Text('Flutter layout demo'),
        ),
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [Text('Hello World')],
          ),
        ),
      ),
    );
  }
}

5. 執行你的應用程式

#

在你加入元件(Widgets)後,請執行你的應用程式。當你執行 應用程式時,應該會看到 Hello World

應用程式原始碼:

Screenshot of app displaying Hello World

垂直與水平排列多個元件(Widgets)

#

最常見的版面配置模式之一,就是將元件(Widgets) 垂直或水平排列。你可以使用 Row 元件來水平排列元件, 使用 Column 元件來垂直排列元件。

要在 Flutter 中建立 row 或 column,只需將一個子元件(Widgets)清單 加入 RowColumn 元件。每個子元件本身 也可以是 row 或 column,如此類推。 以下範例展示了如何在 row 或 column 內巢狀放置 row 或 column。

這個版面配置以 Row 為主體。該 row 包含兩個子元件: 左側是一個 column,右側是一張圖片:

Screenshot with callouts showing the row containing two children

左側 column 的元件樹中巢狀了多個 row 與 column。

Diagram showing a left column broken down to its sub-rows and sub-columns

你將在 巢狀 row 與 column 中實作 Pavlova 的部分版面配置程式碼。

對齊元件(Widgets)

#

你可以透過 mainAxisAlignmentcrossAxisAlignment 屬性來控制 row 或 column 如何對齊其子元件。 對於 row,主軸(main axis)為水平方向,交叉軸(cross axis)為垂直方向。 對於 column,主軸為垂直方向,交叉軸為水平方向。

Diagram showing the main axis and cross axis for a row
Diagram showing the main axis and cross axis for a column

MainAxisAlignmentCrossAxisAlignment 列舉型別(enum)提供多種常數,可用來控制對齊方式。

在下列範例中,每張圖片寬度皆為 100 像素。 渲染區域(本例為整個螢幕)寬度超過 300 像素,因此將主軸對齊設為 spaceEvenly 會讓多餘的水平空間平均分配在每張圖片的前後與之間。

dart
Row(
  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  children: [
    Image.asset('images/pic1.jpg'),
    Image.asset('images/pic2.jpg'),
    Image.asset('images/pic3.jpg'),
  ],
);
Row with 3 evenly spaced images

App source: row_column

Column(欄)與 Row(列)的運作方式相同。以下範例展示了一個包含 3 張圖片的 column,每張圖片高度為 100 像素。Render box(渲染區塊)的高度(在此例中為整個螢幕)大於 300 像素,因此將主軸對齊方式設為 spaceEvenly 時,會將多餘的垂直空間平均分配在每張圖片之間、上方與下方。

dart
Column(
  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  children: [
    Image.asset('images/pic1.jpg'),
    Image.asset('images/pic2.jpg'),
    Image.asset('images/pic3.jpg'),
  ],
);
Column showing 3 images spaced evenly

應用程式原始碼: row_column

元件尺寸調整

#

當版面配置過大,無法完全顯示於裝置螢幕時,受影響的邊緣會出現黃黑相間的條紋圖案。 以下是一個row 過寬的範例

Overly-wide row

可以透過使用 Expanded 元件,讓元件尺寸適合在 row 或 column 內顯示。若要修正前述圖片 row 超出其 render box 的情況, 請將每個圖片包裹在 Expanded 元件中。

dart
Row(
  crossAxisAlignment: CrossAxisAlignment.center,
  children: [
    Expanded(child: Image.asset('images/pic1.jpg')),
    Expanded(child: Image.asset('images/pic2.jpg')),
    Expanded(child: Image.asset('images/pic3.jpg')),
  ],
);
三張圖片排成一列,每張圖片寬度過大,但都被限制只能佔用 1/3 空間

應用程式原始碼: sizing

有時你可能希望某個元件(Widget)佔據比其他同列元件多兩倍的空間。此時,可以使用 Expanded 元件的 flex 屬性,這是一個整數,用來決定該元件的彈性係數(flex factor)。預設的彈性係數為 1。以下程式碼將中間圖片的彈性係數設為 2:

dart
Row(
  crossAxisAlignment: CrossAxisAlignment.center,
  children: [
    Expanded(child: Image.asset('images/pic1.jpg')),
    Expanded(flex: 2, child: Image.asset('images/pic2.jpg')),
    Expanded(child: Image.asset('images/pic3.jpg')),
  ],
);
三張圖片一排,中間那張的寬度是其他兩張的兩倍

應用程式原始碼: sizing

元件(Widgets)打包(Packing)

#

預設情況下,row 或 column 會沿著其主軸(main axis)盡可能佔據空間,但如果你希望讓子元件(children)緊密排列,可以將其 mainAxisSize 設為 MainAxisSize.min。以下範例使用此屬性,將星形圖示元件(icon widgets)緊密排列在一起。

dart
Row(
  mainAxisSize: MainAxisSize.min,
  children: [
    Icon(Icons.star, color: Colors.green[500]),
    Icon(Icons.star, color: Colors.green[500]),
    Icon(Icons.star, color: Colors.green[500]),
    const Icon(Icons.star, color: Colors.black),
    const Icon(Icons.star, color: Colors.black),
  ],
)
Row of 5 stars, packed together in the middle of the row

應用程式原始碼: pavlova

巢狀的 row 與 column

#

版面配置框架允許你在 row 與 column 之中,依需求任意深度地巢狀 row 與 column。 讓我們來看看下方版面配置中紅框標示區塊的程式碼:

Screenshot of the pavlova app, with the ratings and icon rows outlined in red

紅框標示的區塊是由兩個 row 實作而成。評分 row 包含五顆星星與評論數量。圖示 row 則包含三個由圖示與文字組成的 column。

評分 row 的元件樹(widget tree)如下:

Ratings row widget tree

ratings 變數建立了一個 row,其中包含一個較小的 5 星圖示 row,以及文字:

dart
final stars = Row(
  mainAxisSize: MainAxisSize.min,
  children: [
    Icon(Icons.star, color: Colors.green[500]),
    Icon(Icons.star, color: Colors.green[500]),
    Icon(Icons.star, color: Colors.green[500]),
    const Icon(Icons.star, color: Colors.black),
    const Icon(Icons.star, color: Colors.black),
  ],
);

final ratings = Container(
  padding: const EdgeInsets.all(20),
  child: Row(
    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
    children: [
      stars,
      const Text(
        '170 Reviews',
        style: TextStyle(
          color: Colors.black,
          fontWeight: FontWeight.w800,
          fontFamily: 'Roboto',
          letterSpacing: 0.5,
          fontSize: 20,
        ),
      ),
    ],
  ),
);

在評分列(ratings row)下方的圖示列(icons row)包含 3 個欄位,每個欄位內都有一個圖示和兩行文字,如下圖的元件樹(widget tree)所示:

Icon widget tree

iconList 變數定義了圖示列(icons row):

dart
const descTextStyle = TextStyle(
  color: Colors.black,
  fontWeight: FontWeight.w800,
  fontFamily: 'Roboto',
  letterSpacing: 0.5,
  fontSize: 18,
  height: 2,
);

// DefaultTextStyle.merge() allows you to create a default text
// style that is inherited by its child and all subsequent children.
final iconList = DefaultTextStyle.merge(
  style: descTextStyle,
  child: Container(
    padding: const EdgeInsets.all(20),
    child: Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: [
        Column(
          children: [
            Icon(Icons.kitchen, color: Colors.green[500]),
            const Text('PREP:'),
            const Text('25 min'),
          ],
        ),
        Column(
          children: [
            Icon(Icons.timer, color: Colors.green[500]),
            const Text('COOK:'),
            const Text('1 hr'),
          ],
        ),
        Column(
          children: [
            Icon(Icons.restaurant, color: Colors.green[500]),
            const Text('FEEDS:'),
            const Text('4-6'),
          ],
        ),
      ],
    ),
  ),
);

leftColumn 變數包含評分與圖示列,以及描述 Pavlova 的標題和文字:

dart
final leftColumn = Container(
  padding: const EdgeInsets.fromLTRB(20, 30, 20, 20),
  child: Column(children: [titleText, subTitle, ratings, iconList]),
);

左側欄位被放置在SizedBox中,以限制其寬度。 最後,整個 UI 是將整行(包含左側欄位和圖片)放在Card內建構而成。

Pavlova 圖片來自 Pixabay。 你可以使用Image.network()從網路嵌入圖片,但在本範例中,圖片被儲存於專案的 images 目錄,並新增至 pubspec file,然後透過Images.asset()來存取。 如需更多資訊,請參閱新增資源與圖片

dart
body: Center(
  child: Container(
    margin: const EdgeInsets.fromLTRB(0, 40, 0, 30),
    height: 600,
    child: Card(
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          SizedBox(width: 440, child: leftColumn),
          mainImage,
        ],
      ),
    ),
  ),
),

App 原始碼: pavlova


常用版面配置元件 (Layout widgets)

#

Flutter 擁有豐富的版面配置元件 (Layout widgets) 函式庫。以下介紹幾個最常用的元件,目的是讓你能快速上手,而不是給你一份完整清單。若需查詢其他可用元件,請參考 Widget catalog,或在 API 文件 的搜尋框中查找。此外,API 文件中的元件頁面通常也會建議其他可能更適合你需求的相似元件。

以下元件分為兩類:來自 widgets library 的標準元件,以及來自 Material library 的專用元件。任何應用程式都可以使用 widgets library,但只有 Material 應用程式可以使用 Material Components library。

Container
為元件 (Widget) 增加內距(padding)、外距(margin)、邊框、背景顏色或其他裝飾效果。
GridView
以可捲動的網格方式排列元件。
ListView
以可捲動的清單方式排列元件。
Stack
將一個元件重疊顯示在另一個元件之上。
Scaffold
提供結構化的版面配置框架,包含常見 Material Design 應用程式元素的插槽。
AppBar
建立一個通常顯示在螢幕頂部的水平列。
Card
將相關資訊組織在一個帶有圓角和陰影的方框中。
ListTile
將最多三行文字,以及可選的前置與後置圖示,組成一個橫向排列的列。
CupertinoPageScaffold
提供 iOS 風格頁面的基本版面結構。
CupertinoNavigationBar
在螢幕頂部建立 iOS 風格的導覽列。
CupertinoSegmentedControl
建立 iOS 風格的分段控制元件,用於選擇。
CupertinoTabBarCupertinoTabScaffold
建立 iOS 典型的底部分頁列。

Container

#

許多版面配置會大量使用 Container 來透過內距(padding)分隔元件,或是增加邊框與外距(margin)。你可以將整個版面包在一個 Container 中,並更改其背景顏色或圖片,以改變裝置背景。

摘要(Container)

#
  • 增加內距(padding)、外距(margin)、邊框
  • 更改背景顏色或圖片
  • 僅包含一個子元件(child),但該子元件可以是 RowColumn,甚至是元件樹的根節點
Diagram showing: margin, border, padding, and content

範例(Container)

#

此版面由一個包含兩列的 column 組成,每一列各有兩張圖片。利用 Container 將 column 的背景色設為較淺的灰色。

dart
Widget _buildImageColumn() {
  return Container(
    decoration: const BoxDecoration(color: Colors.black26),
    child: Column(children: [_buildImageRow(1), _buildImageRow(3)]),
  );
}
Screenshot showing 2 rows, each containing 2 images

Container 也用來為每張圖片新增圓角邊框和邊距:

dart
Widget _buildDecoratedImage(int imageIndex) => Expanded(
  child: Container(
    decoration: BoxDecoration(
      border: Border.all(width: 10, color: Colors.black38),
      borderRadius: const BorderRadius.all(Radius.circular(8)),
    ),
    margin: const EdgeInsets.all(4),
    child: Image.asset('images/pic$imageIndex.jpg'),
  ),
);

Widget _buildImageRow(int imageIndex) => Row(
  children: [
    _buildDecoratedImage(imageIndex),
    _buildDecoratedImage(imageIndex + 1),
  ],
);

你可以在 教學課程 中找到更多 Container 範例。

應用程式原始碼: container


GridView

#

使用 GridView 將元件(Widgets)以二維清單方式排列。GridView 提供兩種預設的清單,或是你也可以自訂自己的格線。當 GridView 偵測到內容過長無法完全顯示於 render box 時,會自動產生捲動功能。

摘要(GridView)

#
  • 以格線方式排列元件(Widgets)
  • 偵測當欄內容超出 render box 時,自動提供捲動功能
  • 你可以自訂自己的格線,或使用以下其中一種預設格線:
    • GridView.count 可讓你指定欄位數量
    • GridView.extent 可讓你指定每個格子(tile)的最大像素寬度

範例(GridView)

#
A 3-column grid of photos

使用 GridView.extent 建立一個每個格子最大寬度為 150 像素的格線。

應用程式原始碼: grid_and_list

A 2 column grid with footers

使用 GridView.count 建立一個在直向模式下有 2 欄、橫向模式下有 3 欄的格線。標題是透過為每個 GridTile 設定 footer 屬性產生。

Dart 程式碼: grid_list_demo.dart

dart
Widget _buildGrid() => GridView.extent(
  maxCrossAxisExtent: 150,
  padding: const EdgeInsets.all(4),
  mainAxisSpacing: 4,
  crossAxisSpacing: 4,
  children: _buildGridTileList(30),
);

// The images are saved with names pic0.jpg, pic1.jpg...pic29.jpg.
// The List.generate() constructor allows an easy way to create
// a list when objects have a predictable naming pattern.
List<Widget> _buildGridTileList(int count) =>
    List.generate(count, (i) => Image.asset('images/pic$i.jpg'));

ListView

#

ListView 是一個類似直欄的元件(Widget),當內容超出其繪製區域時,會自動提供滾動功能。

摘要(ListView)

#
  • 一個專門用於組織方塊清單的 Column
  • 可以橫向或縱向排列
  • 能偵測內容無法容納時自動提供滾動
  • 可配置性較 Column 低,但更易於使用且支援滾動

範例(ListView)

#
ListView containing movie theaters and restaurants

使用 ListView 來顯示一個包含多家商家的清單,並以 ListTiles 呈現。Divider 用來將電影院與餐廳分隔開。

App 原始碼: grid_and_list

ListView containing shades of blue

使用 ListView 來顯示 Colors,這些顏色來自 Material 2 Design palette 的某個色系。

Dart 程式碼: colors_demo.dart

dart
Widget _buildList() {
  return ListView(
    children: [
      _tile('CineArts at the Empire', '85 W Portal Ave', Icons.theaters),
      _tile('The Castro Theater', '429 Castro St', Icons.theaters),
      _tile('Alamo Drafthouse Cinema', '2550 Mission St', Icons.theaters),
      _tile('Roxie Theater', '3117 16th St', Icons.theaters),
      _tile(
        'United Artists Stonestown Twin',
        '501 Buckingham Way',
        Icons.theaters,
      ),
      _tile('AMC Metreon 16', '135 4th St #3000', Icons.theaters),
      const Divider(),
      _tile('K\'s Kitchen', '757 Monterey Blvd', Icons.restaurant),
      _tile('Emmy\'s Restaurant', '1923 Ocean Ave', Icons.restaurant),
      _tile('Chaiya Thai Restaurant', '272 Claremont Blvd', Icons.restaurant),
      _tile('La Ciccia', '291 30th St', Icons.restaurant),
    ],
  );
}

ListTile _tile(String title, String subtitle, IconData icon) {
  return ListTile(
    title: Text(
      title,
      style: const TextStyle(fontWeight: FontWeight.w500, fontSize: 20),
    ),
    subtitle: Text(subtitle),
    leading: Icon(icon, color: Colors.blue[500]),
  );
}

Stack

#

使用 Stack 來將元件(Widgets)堆疊在一個基礎元件之上——通常是一張圖片。這些元件可以完全或部分地重疊在基礎元件上。

摘要(Stack)

#
  • 適用於需要重疊在其他元件上的元件
  • children 清單中的第一個元件是基礎元件;後續的子元件會疊加在該基礎元件之上
  • Stack 的內容無法滾動
  • 你可以選擇裁剪超出 render box 的子元件

範例(Stack)

#
Circular avatar image with a label

使用 Stack 疊加一個 Container(其會在半透明黑色背景上顯示其 Text)於 CircleAvatar 之上。Stack 透過 alignment 屬性與 Alignment 來偏移文字。

App 原始碼: card_and_stack

An image with a icon overlaid on top

使用 Stack 疊加一個圖示於圖片之上。

Dart 程式碼: bottom_navigation_demo.dart

dart
Widget _buildStack() {
  return Stack(
    alignment: const Alignment(0.6, 0.6),
    children: [
      const CircleAvatar(
        backgroundImage: AssetImage('images/pic.jpg'),
        radius: 100,
      ),
      Container(
        decoration: const BoxDecoration(color: Colors.black45),
        child: const Text(
          'Mia B',
          style: TextStyle(
            fontSize: 20,
            fontWeight: FontWeight.bold,
            color: Colors.white,
          ),
        ),
      ),
    ],
  );
}

Card

#

一個 Card,來自 Material library, 用於承載相關的資訊片段,可以由幾乎任何元件(Widget)組成,但通常會與 ListTile 一起使用。Card 僅接受一個子元件, 但其子元件可以是 column、row、list、grid, 或其他支援多個子元件的元件。 預設情況下,Card 會將自身尺寸縮小為 0 x 0 像素。 你可以使用 SizedBox 來限制 card 的尺寸。

在 Flutter 中,Card 具有略為圓角的邊緣 以及投影陰影,帶來 3D 效果。 變更 Cardelevation 屬性可以控制 投影陰影的效果。例如,將 elevation 設為 24, 會讓 Card 視覺上從表面抬升得更高,且陰影會更加分散。 支援的 elevation 值請參考 ElevationMaterial guidelines。 若指定不支援的值,則會完全關閉投影陰影。

摘要(Card)

#
  • 實作 Material card
  • 用於呈現相關的資訊片段
  • 僅接受一個子元件,但該子元件可以是 RowColumn,或其他可包含多個子元件的元件
  • 以圓角與投影陰影顯示
  • Card 的內容無法滾動
  • 來自 Material library

範例(Card)

#
Card containing 3 ListTiles

一個 Card,內含 3 個 ListTile,並透過包裹 SizedBox 來設定尺寸。Divider 用於分隔 第一個與第二個 ListTiles

App 原始碼: card_and_stack

Tappable card containing an image and multiple forms of text

一個 Card,內含圖片與文字。

Dart 程式碼: cards_demo.dart

dart
Widget _buildCard() {
  return SizedBox(
    height: 210,
    child: Card(
      child: Column(
        children: [
          ListTile(
            title: const Text(
              '1625 Main Street',
              style: TextStyle(fontWeight: FontWeight.w500),
            ),
            subtitle: const Text('My City, CA 99984'),
            leading: Icon(Icons.restaurant_menu, color: Colors.blue[500]),
          ),
          const Divider(),
          ListTile(
            title: const Text(
              '(408) 555-1212',
              style: TextStyle(fontWeight: FontWeight.w500),
            ),
            leading: Icon(Icons.contact_phone, color: Colors.blue[500]),
          ),
          ListTile(
            title: const Text('costa@example.com'),
            leading: Icon(Icons.contact_mail, color: Colors.blue[500]),
          ),
        ],
      ),
    ),
  );
}

ListTile

#

使用 ListTile,這是一個來自 Material library 的專用 row 元件(Widget),可以輕鬆建立一個 row,內含最多 3 行文字,並可選擇性加入前置(leading)及後置(trailing)圖示。ListTile 最常用於 CardListView,但也可用於其他地方。

摘要(ListTile)

#
  • 一個專用的 row,可包含最多 3 行文字及可選的圖示
  • 可設定性比 Row 少,但更容易使用
  • 來自 Material library

範例(ListTile)

#
Card containing 3 ListTiles

一個 Card,內含 3 個 ListTile

App 原始碼: card_and_stack

4 ListTiles, each containing a leading avatar

使用帶有前置元件(leading widgets)的 ListTile

Dart 程式碼: list_demo.dart


限制條件(Constraints)

#

若要完全理解 Flutter 的版面配置系統,你需要學習 Flutter 如何在版面中定位與調整元件(components)的大小。更多資訊請參閱 Understanding constraints

影片

#

以下影片為 Flutter in Focus 系列的一部分,說明 StatelessStateful 元件(Widgets)。

Watch on YouTube in a new tab: "How to create stateless widgets"

Watch on YouTube in a new tab: "How and when stateful widgets are best used"

Flutter in Focus 播放清單


每一集 Widget of the Week series 都會聚焦介紹一個元件(Widget),其中有多集包含版面配置元件(Layout widgets)。

Watch on YouTube in a new tab: "Introducing widget of the week"

Flutter Widget of the Week 播放清單

其他資源

#

以下資源在撰寫版面配置程式碼時可能有所幫助。

Layout tutorial
學習如何建立版面配置。
Widget catalog
介紹 Flutter 提供的多種元件(Widgets)。
HTML/CSS Analogs in Flutter
若你熟悉網頁程式設計,本頁將 HTML/CSS 的功能對應到 Flutter 的特性。
API reference docs
提供所有 Flutter 函式庫的參考文件。
Adding assets and images
說明如何將圖片及其他資源加入你的應用程式套件中。
Zero to One with Flutter
一位開發者撰寫其第一個 Flutter 應用程式的經驗分享。