flutter-fix-layout-issues

flutter-fix-layout-issues

熱門

使用 Dart 和 Flutter MCP 工具修復 Flutter 版面配置錯誤(溢出、無限制約束)。適用於處理「RenderFlex overflowed」、「Vertical viewport was given unbounded height」或類似版面配置問題。

2525星標
152分支
更新於 2026/6/18
SKILL.md
readonlyread-only
name
flutter-fix-layout-issues
description

Fixes Flutter layout errors (overflows, unbounded constraints) using Dart and Flutter MCP tools. Use when addressing "RenderFlex overflowed", "Vertical viewport was given unbounded height", or similar layout issues.

解決 Flutter 版面配置錯誤

目錄

約束違規診斷

Flutter 版面配置遵循嚴格規則:約束向下傳遞。尺寸向上回報。父層設定位置。 當此協商失敗時,就會發生版面配置錯誤,通常是因為無限制約束或未受約束的子元件。

根據以下錯誤特徵診斷版面配置失敗:

  • 「Vertical viewport was given unbounded height」:當可滾動元件(ListViewGridView)被放置在無垂直約束的父層(Column)內部時觸發。父層提供無限高度,子元件嘗試無限擴展。
  • 「An InputDecorator...cannot have an unbounded width」:當 TextFieldTextFormField 被放置在無水平約束的父層(Row)內部時觸發。文字欄位嘗試根據無限可用空間決定其寬度。
  • 「RenderFlex overflowed」:當 RowColumn 的子元件請求的尺寸大於父層分配的約束時觸發。視覺上會出現黃色和黑色警告條紋。
  • 「Incorrect use of ParentData widget」:當 ParentDataWidget 不是其必要祖先的直接後代時觸發(例如,Expanded 不在 Flex 內,Positioned 不在 Stack 內)。
  • 「RenderBox was not laid out」:這是一個連鎖副作用錯誤。請忽略此錯誤,並在堆疊追蹤中向上尋找主要的約束違規(通常是無限制高度/寬度錯誤)。

版面配置錯誤解決流程

複製並使用此檢查清單,系統性地解決版面配置約束違規。

任務進度

  • [ ] 以除錯模式執行應用程式,在控制台中擷取確切的版面配置例外。
  • [ ] 識別主要錯誤訊息(忽略連鎖的「RenderBox was not laid out」錯誤)。
  • [ ] 根據特定錯誤類型套用條件式修復:
    • 如果出現「Vertical viewport was given unbounded height」:將可滾動子元件(ListViewGridView)包在 Expanded 元件中以佔用剩餘空間,或將其包在 SizedBox 中以提供絕對高度約束。
    • 如果出現「An InputDecorator...cannot have an unbounded width」:將 TextFieldTextFormField 包在 ExpandedFlexible 元件中。
    • 如果出現「RenderFlex overflowed」:將溢出的子元件包在 Expanded 元件中(強制其適應)或 Flexible 元件中(允許其小於分配的空間)。
    • 如果出現「Incorrect use of ParentData widget」:將 ParentDataWidget 移動為其必要父層的直接子元件。確保 Expanded/FlexibleRow/Column/Flex 的直接子元件。確保 PositionedStack 的直接子元件。
  • [ ] 執行 Flutter 熱重新載入。
  • [ ] 執行驗證器 -> 檢視錯誤 -> 修復:檢查 UI,確認紅色/灰色錯誤畫面或黃色/黑色溢出條紋已解決。如果出現新的版面配置錯誤,請重複此流程。

範例

修復無限制高度(Column 中的 ListView)

輸入(錯誤狀態):

// 拋出「Vertical viewport was given unbounded height」
Column(
  children: <Widget>[
    const Text('Header'),
    ListView(
      children: const <Widget>[
        ListTile(title: Text('Item 1')),
        ListTile(title: Text('Item 2')),
      ],
    ),
  ],
)

輸出(已解決狀態):

// 將 ListView 包在 Expanded 中,將其高度限制在 Column 的剩餘空間
Column(
  children: <Widget>[
    const Text('Header'),
    Expanded(
      child: ListView(
        children: const <Widget>[
          ListTile(title: Text('Item 1')),
          ListTile(title: Text('Item 2')),
        ],
      ),
    ),
  ],
)

修復無限制寬度(Row 中的 TextField)

輸入(錯誤狀態):

// 拋出「An InputDecorator...cannot have an unbounded width」
Row(
  children: [
    const Icon(Icons.search),
    TextField(), 
  ],
)

輸出(已解決狀態):

// 將 TextField 包在 Expanded 中,將其寬度限制在 Row 的剩餘空間
Row(
  children: [
    const Icon(Icons.search),
    Expanded(
      child: TextField(),
    ),
  ],
)

修復 RenderFlex 溢出

輸入(錯誤狀態):

// 拋出「A RenderFlex overflowed by X pixels on the right」
Row(
  children: [
    const Icon(Icons.info),
    const Text('This is a very long text string that will definitely overflow the available screen width and cause a RenderFlex error.'),
  ],
)

輸出(已解決狀態):

// 將 Text 元件包在 Expanded 中,強制其在可用約束內換行
Row(
  children: [
    const Icon(Icons.info),
    Expanded(
      child: const Text('This is a very long text string that will definitely overflow the available screen width and cause a RenderFlex error.'),
    ),
  ],
)