Flutter 中的配置

Flutter 配置機制的核心是小工具。在 Flutter 中,幾乎所有東西都是小工具,甚至配置模型也是小工具。您在 Flutter 應用程式中看到的圖片、圖示和文字都是小工具。但您看不到的東西也是小工具,例如排列、限制和對齊可見小工具的列、欄和格線。

透過組合小工具來建立更複雜的小工具,您可以建立配置。例如,以下第一個螢幕截圖顯示 3 個圖示,每個圖示下方都有標籤

Sample layout Sample layout with visual debugging

第二個螢幕截圖顯示視覺配置,顯示 3 個欄的列,每個欄包含一個圖示和一個標籤。

以下是這個使用者介面的樹狀小工具圖表

Node tree

大部分內容應該看起來符合您的預期,但您可能會好奇容器(以粉紅色顯示)。Container 是一個小工具類別,讓您可以自訂其子小工具。當您想要新增內距、外距、邊框或背景顏色時,請使用 Container,這是其部分功能。

在此範例中,每個 Text 小工具都放置在 Container 中,以新增外距。整個 Row 也放置在 Container 中,以在列周圍新增內距。

此範例中其餘的 UI 由屬性控制。使用 Iconcolor 屬性設定圖示的顏色。使用 Text.style 屬性設定字型、顏色、粗細等。欄和列有屬性可讓您指定其子項目的垂直或水平對齊方式,以及子項目應佔用的空間大小。

配置小工具

如何在 Flutter 中配置單一小工具?本節將說明如何建立並顯示簡單的小工具。它也會顯示簡單 Hello World 應用程式的完整程式碼。

在 Flutter 中,只要幾個步驟就能在螢幕上放置文字、圖示或影像。

1. 選擇配置小工具

根據您要如何對齊或限制可見小工具,從各種 配置小工具 中進行選擇,因為這些特性通常會傳遞給所包含的小工具。

此範例使用 Center,它會將其內容置中在水平和垂直方向上。

2. 建立可見小工具

例如,建立 Text 小工具

Text('Hello World'),

建立 Image 小工具

return Image.asset(
  image,
  fit: BoxFit.cover,
);

建立一個 Icon 小工具

Icon(
  Icons.star,
  color: Colors.red[500],
),

3. 將可見小工具加入版面配置小工具

所有版面配置小工具都有下列任一屬性

  • 如果只有一個子項,則有 child 屬性,例如 CenterContainer
  • 如果有一串小工具,則有 children 屬性,例如 RowColumnListViewStack

Text 小工具加入 Center 小工具

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

4. 將版面配置小工具加入頁面

Flutter 應用程式本身就是一個小工具,而大多數小工具都有 build() 方法。在應用程式的 build() 方法中實例化並傳回小工具,即可顯示小工具。

Material 應用程式

對於 Material 應用程式,可以使用 Scaffold 小工具;它提供預設橫幅、背景顏色,並有 API 可加入抽屜、小吃欄和底部工作表。然後,你可以將 Center 小工具直接加入首頁的 body 屬性。

lib/main.dart (MyApp)
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 應用程式

要建立 Cupertino 應用程式,請使用 CupertinoAppCupertinoPageScaffold 小工具。

Material 不同,它不提供預設橫幅或背景顏色。您需要自行設定這些。

  • 若要設定預設顏色,請傳入已設定的 CupertinoThemeData 至應用程式的 theme 屬性。
  • 若要將 iOS 風格的導覽列新增至應用程式的頂端,請將 CupertinoNavigationBar 小工具新增至鷹架的 navigationBar 屬性。您可以使用 CupertinoColors 提供的顏色來設定小工具以符合 iOS 設計。

  • 若要配置應用程式的內文,請將鷹架的 child 屬性設定為所需小工具,其值為 CenterColumn

若要瞭解可以新增哪些其他 UI 元件,請查看 Cupertino 函式庫

lib/cupertino.dart (MyApp)
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: <Widget>[
              Text('Hello World'),
            ],
          ),
        ),
      ),
    );
  }
}

非 Material 應用程式

對於非 Material 應用程式,可以將 Center 元件新增到應用程式的 build() 方法

lib/main.dart (MyApp)
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,
          ),
        ),
      ),
    );
  }
}

預設情況下,非 Material 應用程式不包含 AppBar、標題或背景顏色。如果要在非 Material 應用程式中使用這些功能,必須自行建立。此應用程式將背景顏色變更為白色,文字變更為深灰色,以模擬 Material 應用程式。

完成!執行應用程式後,您應該會看到 Hello World

應用程式原始碼

Hello World

垂直和水平配置多個元件

最常見的配置模式之一是垂直或水平配置元件。可以使用 Row 元件水平配置元件,並使用 Column 元件垂直配置元件。

要在 Flutter 中建立列或欄,請將子小工具清單新增到 RowColumn 小工具。反過來,每個子項本身都可以是列或欄,依此類推。以下範例顯示如何在列或欄內嵌套列或欄。

此版面組織成 Row。此列包含兩個子項:左邊的欄和右邊的圖片。

Screenshot with callouts showing the row containing two children

左欄的小工具樹嵌套列和欄。

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

你會在 嵌套列和欄 中實作一些 Pavlova 的版面程式碼。

對齊小工具

您可以使用 mainAxisAlignmentcrossAxisAlignment 屬性控制列或欄對齊其子項目的方式。對於列,主軸線水平運行,而交叉軸線垂直運行。對於欄,主軸線垂直運行,而交叉軸線水平運行。

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

MainAxisAlignmentCrossAxisAlignment 枚舉提供各種控制對齊的常數。

在以下範例中,3 個圖片的寬度各為 100 像素。渲染方塊(在本例中為整個畫面)的寬度超過 300 像素,因此將主軸線對齊設定為 spaceEvenly 會在每個圖片的前後均勻分配多餘的水平空間。

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

應用程式來源: row_column

欄位與列運作方式相同。下列範例顯示 3 個影像的欄位,每個影像高度為 100 個像素。呈現方塊的高度(在本例中,為整個畫面)大於 300 個像素,因此將主軸對齊設定為 spaceEvenly,會將多餘的垂直空間平均分配在每個影像的上方、下方和中間。

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

應用程式來源: row_column

Column showing 3 images spaced evenly

調整小工具大小

當版面過大而無法裝置在裝置上時,受影響的邊緣會出現黃色和黑色的條紋圖案。以下是一個 範例,說明列太寬

Overly-wide row

可以使用 Expanded 小工具,調整小工具大小以符合列或欄位。要修正前一個範例中影像列過寬的問題,請使用 Expanded 小工具包裝每個影像。

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'),
    ),
  ],
);

Row of 3 images that are too wide, but each is constrained to take only 1/3 of the space

應用程式來源: 調整大小

您可能希望小工具佔用與其同層級項目兩倍的空間。為此,請使用 Expanded 小工具 flex 屬性,這是一個整數,用於決定小工具的彈性係數。預設彈性係數為 1。下列程式碼將中間影像的彈性係數設定為 2

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'),
    ),
  ],
);

Row of 3 images with the middle image twice as wide as the others

應用程式來源: 調整大小

包裝小工具

預設情況下,列或欄位會在其主軸上佔用盡可能多的空間,但如果您想將子項緊密地包裝在一起,請將其 mainAxisSize 設定為 MainAxisSize.min。下列範例使用此屬性將星星圖示包裝在一起。

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

巢狀列和欄

佈局架構讓您能將列和欄巢狀置於列和欄中,深度不限。我們來看以下佈局中,輪廓部分的程式碼

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

輪廓部分實作為兩列。評分列包含五顆星和評論數。圖示列包含三欄的圖示和文字。

評分列的小工具樹狀結構

Ratings row widget tree

ratings 變數建立一列,包含一列較小的 5 顆星圖示和文字

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,
        ),
      ),
    ],
  ),
);

評分列下方的圖示列包含 3 欄;每欄包含一個圖示和兩行文字,如您在小工具樹狀結構中所見

Icon widget tree

iconList 變數定義圖示列

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 的文字

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 檔案,並使用 Images.asset() 存取。如需更多資訊,請參閱 新增資源和圖片

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,
        ],
      ),
    ),
  ),
),

應用程式來源: pavlova


常見配置小工具

Flutter 擁有豐富的配置小工具函式庫。以下是其中幾個最常用的。目的是讓您盡快上手,而不是讓您因完整的清單而不知所措。如需有關其他可用小工具的資訊,請參閱 小工具目錄,或使用 API 參考文件 中的搜尋方塊。此外,API 文件中的小工具頁面通常會建議更適合您需求的類似小工具。

下列小工具分為兩類:小工具函式庫 中的標準小工具,以及 Material 函式庫 中的專用小工具。任何應用程式都可以使用小工具函式庫,但只有 Material 應用程式可以使用 Material Components 函式庫。

標準小工具

  • Container:為小工具新增內距、外距、邊框、背景顏色或其他裝飾。
  • GridView:將小工具配置為可捲動的格線。
  • ListView:以可捲動清單的形式排列小工具。
  • Stack:將一個小工具疊放在另一個小工具之上。

材質小工具

  • Card:將相關資訊整理到一個帶有圓角和陰影的方塊中。
  • ListTile:將最多 3 行文字,以及可選的置中和置尾圖示,整理成一行。

容器

許多版面配置大量使用 Container 來使用內距分隔小工具,或新增邊框或外距。您可以透過將整個版面配置放入 Container 中,並變更其背景顏色或圖片,來變更裝置的背景。

摘要 (Container)

  • 新增內距、外距、邊框
  • 變更背景顏色或圖片
  • 包含一個單一子小工具,但該子小工具可以是 Row、Column,甚至是小工具樹的根目錄
Diagram showing: margin, border, padding, and content

範例 (Container)

此版面配置由兩列組成,每列包含 2 個圖片。一個 Container 用於將該欄的背景顏色變更為較淺的灰色。

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 也用於為每個圖片新增圓形邊框和外距

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 將小工具配置為二維清單。 GridView 提供兩個預製清單,或者您可以建立自己的自訂格線。當 GridView 偵測到其內容過長而無法符合渲染方塊時,它會自動捲動。

摘要 (GridView)

  • 將小工具配置在格線中
  • 偵測到欄位內容超過渲染方塊時,並自動提供捲動功能
  • 建立自己的自訂格線,或使用其中一個提供的格線
    • GridView.count 讓您可以指定欄位數目
    • GridView.extent 讓您可以指定磁磚的最大像素寬度

範例 (GridView)

A 3-column grid of photos

使用 GridView.extent 建立一個格線,其中磁磚的最大寬度為 150 像素。

應用程式來源: grid_and_list

A 2 column grid with footers

使用 GridView.count 建立一個在直立模式下為 2 個磁磚寬,在橫向模式下為 3 個磁磚寬的網格。標題是透過設定每個 GridTilefooter 屬性建立的。

Dart 程式碼: grid_list_demo.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<Container> _buildGridTileList(int count) => List.generate(
    count, (i) => Container(child: Image.asset('images/pic$i.jpg')));

ListView

ListView 是一個類似欄的元件,當其內容過長而無法顯示在渲染方塊中時,會自動提供捲動功能。

摘要 (ListView)

  • 一個用於整理方塊清單的特殊 Column
  • 可以水平或垂直配置
  • 偵測其內容是否無法顯示並提供捲動功能
  • 可設定性低於 Column,但較容易使用且支援捲動

範例 (ListView)

ListView containing movie theaters and restaurants

使用 ListView 顯示使用 ListTile 的商家清單。一個 Divider 將戲院與餐廳分開。

應用程式來源: grid_and_list

ListView containing shades of blue

使用 ListView 顯示 ColorsMaterial 2 Design 色彩盤 中的特定色彩系列。

Dart 程式碼: colors_demo.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 將小工具排列在基礎小工具上,通常是影像。小工具可以完全或部分重疊基礎小工具。

摘要 (Stack)

  • 用於重疊其他小工具的小工具
  • 子項清單中的第一個小工具是基礎小工具;後續子項會疊加在該基礎小工具上
  • 無法捲動 Stack 的內容
  • 您可以選擇裁剪超出渲染方塊的子項

範例 (Stack)

Circular avatar image with a label

使用 StackContainer(在半透明黑色背景上顯示其 Text)疊加在 CircleAvatar 上。 Stack 使用 alignment 屬性和 Alignments 來偏移文字。

應用程式來源: card_and_stack

An image with a icon overlaid on top

使用 Stack 將圖示疊加在影像上。

Dart 程式碼: bottom_navigation_demo.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 來自 Material 函式庫,包含相關資訊的片段,且幾乎可以由任何小工具組成,但通常會與 ListTile 搭配使用。 Card 有一個子項,但其子項可以是欄、列、清單、格線或其他支援多個子項的小工具。預設情況下, Card 會將其大小縮小至 0 x 0 像素。您可以使用 SizedBox 來限制卡片的大小。

在 Flutter 中, Card 的特色是邊角略為圓潤,並有投射陰影,營造出 3D 效果。變更 Cardelevation 屬性,可讓您控制投射陰影效果。例如,將高度設為 24,會在視覺上將 Card 從表面進一步拉高,並使陰影更為分散。如需支援的高度值的清單,請參閱 高度,位於 Material 指南 中。指定不支援的值會完全停用投射陰影。

摘要 (卡片)

  • 實作 Material 卡片
  • 用於呈現相關資訊的片段
  • 接受單一子項,但該子項可以是 RowColumn 或其他包含子項清單的小工具
  • 顯示為圓角和投射陰影
  • Card 的內容無法捲動
  • 來自 Material 函式庫

範例 (卡片)

Card containing 3 ListTiles

一個包含 3 個 ListTilesCard,並透過將其與 SizedBox 包覆來調整大小。一個 Divider 區隔第一個和第二個 ListTiles

應用程式來源: card_and_stack

Tappable card containing an image and multiple forms of text

包含圖片和文字的 卡片

Dart 程式碼: cards_demo.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('[email protected]'),
            leading: Icon(
              Icons.contact_mail,
              color: Colors.blue[500],
            ),
          ),
        ],
      ),
    ),
  );
}

清單磚

使用 ListTile,這是 Material 函式庫 中的專用列小工具,可以輕鬆建立包含最多 3 行文字和選用前導和尾隨圖示的列。 ListTile 最常使用於 卡片ListView,但也可以用於其他地方。

摘要 (清單磚)

  • 包含最多 3 行文字和選用圖示的專用列
  • Row 的可設定性較低,但較容易使用
  • 來自 Material 函式庫

範例 (清單磚)

Card containing 3 ListTiles

包含 3 個 ListTile卡片

應用程式來源: card_and_stack

4 ListTiles, each containing a leading avatar

使用帶有前導小工具的 ListTile

Dart 程式碼: list_demo.dart


約束

若要完全了解 Flutter 的配置系統,您需要學習 Flutter 如何配置和調整配置中的元件大小。如需詳細資訊,請參閱 了解約束

影片

以下影片為 Flutter in Focus 系列的一部分,說明 StatelessStateful 小工具。

Flutter in Focus 播放清單


每集 Widget of the Week 系列 都會專注於一個小工具。其中有幾個包含版面配置小工具。

Flutter Widget of the Week 播放清單

其他資源

以下資源可能有助於撰寫版面配置程式碼。