---
# System prepended metadata

title: Flutter - 系統 UI 控制 SystemChrome

---

Flutter - 系統 UI 控制 SystemChrome
===
針對 Flutter 中使用 `SystemChrome` 系統層 UI 控制方式進行說明與實務解法。

## SystemChrome
SystemChrome 是 Flutter 提供用來與底層作業系統（Android / iOS）互動的靜態類別，可控制應用程式的系統 UI 行為。

### 系統 UI 顯示模式
用途： 控制狀態列與導航列的顯示/隱藏方式（全螢幕沉浸模式等）。
```dart
//隱藏底部導航列，狀態列不隱藏
SystemChrome.setEnabledSystemUIMode(
  SystemUiMode.manual,
  overlays: [SystemUiOverlay.top],
);
```

| OPPO 底部導覽頁縮合 | iPhone 顏色切換 |  Samsung 顏色切換 |
| -------- | -------- | -------- |
|![](https://hackmd.io/_uploads/S1p6IPz0yx.gif)| ![](https://hackmd.io/_uploads/r1C9eDf01e.gif)     | ![](https://hackmd.io/_uploads/HyzqmwfC1l.gif)     |
#### 系統 UI 模式（SystemUiMode）
##### 參數說明
| 模式              | 說明 | 適用場景 |
|-------------------|------|----------|
| `edgeToEdge`      | 顯示狀態列與導航列，內容延伸至螢幕邊緣（可設透明） | 多數一般應用 |
| `immersive`       | 隱藏所有系統 UI，需滑動喚出，不會自動隱藏 | 遊戲、全螢幕展示 |
| `immersiveSticky` | 同上，但喚出 UI 後會自動隱藏 | 電子書、影片播放 |
| `leanBack`        | 觸控時顯示 UI，僅支援較舊 Android 裝置 | 特殊需求 |
| `manual`          | 自訂要顯示的 overlay（top/bottom） | 精細控制場景 |
##### 程式範例
```dart
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky);
```
#### 系統 UI 樣式（SystemUiOverlayStyle）
##### 參數說明
| 參數 | 說明 |
|------|------|
| `statusBarColor` | 狀態列背景顏色 |
| `statusBarIconBrightness` | 狀態列 icon 的顏色（light = 白，dark = 黑） |
| `statusBarBrightness` | 僅 iOS：控制狀態列背景亮度 |
| `systemNavigationBarColor` | 底部導覽列背景色 |
| `systemNavigationBarIconBrightness` | 導覽列 icon 顏色亮度 |
| `systemStatusBarContrastEnforced` | 是否強制套用背景對比（Android 10+） |
| `systemNavigationBarContrastEnforced` | 同上，針對導覽列 

iOS 僅支援：
* statusBarBrightness（決定文字為黑或白）
* 不支援 statusBarIconBrightness

##### 程式範例
```dart
// 亮色模式
SystemChrome.setSystemUIOverlayStyle(
  const SystemUiOverlayStyle(
    statusBarColor: Colors.transparent, // 狀態列背景透明（iOS/Android）
    statusBarIconBrightness: Brightness.dark, // Android：黑色 icon（亮背景）
    statusBarBrightness: Brightness.light, // iOS：亮模式
    systemNavigationBarColor: Colors.transparent, // 導航列背景透明
    systemNavigationBarIconBrightness: Brightness.dark,
    systemStatusBarContrastEnforced: false,
    systemNavigationBarContrastEnforced: false,
  ),
);

// 暗色模式
SystemChrome.setSystemUIOverlayStyle(
  const SystemUiOverlayStyle(
    statusBarColor: Colors.transparent,
    statusBarIconBrightness: Brightness.light, // Android：白色 icon（暗背景）
    statusBarBrightness: Brightness.dark, // iOS：暗模式
    systemNavigationBarColor: Colors.transparent,
    systemNavigationBarIconBrightness: Brightness.light,
    systemStatusBarContrastEnforced: false,
    systemNavigationBarContrastEnforced: false,
  ),
);
```

### 裝置方向鎖定
用途： 限制螢幕方向（如：僅允許直立或橫向模式）。

#### 裝置方向鎖定（Device Orientation Lock）

##### 參數說明
| 參數                                | 說明                   |
|-------------------------------------|------------------------|
| `DeviceOrientation.portraitUp`      | 垂直向上（預設手機直立） |
| `DeviceOrientation.portraitDown`    | 垂直向下（較少用）       |
| `DeviceOrientation.landscapeLeft`   | 橫向：向左旋轉           |
| `DeviceOrientation.landscapeRight`  | 橫向：向右旋轉           |

##### 程式範例

```dart
// 僅允許直立模式
await SystemChrome.setPreferredOrientations([
  DeviceOrientation.portraitUp,
]);

// 僅允許橫向模式（左右都可以）
await SystemChrome.setPreferredOrientations([
  DeviceOrientation.landscapeLeft,
  DeviceOrientation.landscapeRight,
]);

// 取消方向鎖定，允許系統根據裝置方向自動切換
await SystemChrome.setPreferredOrientations([]);

//-------------------

// 動態切換方向（例如影片播放頁面進入橫向，返回時恢復直立）
@override
void didChangeDependencies() {
  super.didChangeDependencies();
  // 進入頁面時
  SystemChrome.setPreferredOrientations([
    DeviceOrientation.landscapeLeft,
  ]);
}

@override
void dispose() {
  // 離開頁面時恢復直立
  SystemChrome.setPreferredOrientations([
    DeviceOrientation.portraitUp,
  ]);
  super.dispose();
}
```


## 常見問題與平台差異

### 狀態列出現黑邊（OPPO、小米等機型）

- **原因**：部分 Android 裝置（如 OPPO、小米）在 immersive 模式下，即使隱藏狀態列，系統仍會保留繪製背景區塊，預設為黑色。

補充 OPPO、小米、Vivo 等裝置可能即使已設為透明，建議實機測試，另外目前有遇到縮合 status bar 會造成使用者有感 APP 重新繪製造成體感不佳的問題，建議不縮合 status bar

### immersive 模式下 AppBar 無法點擊

- **原因**：Android 系統保留頂部約 24dp 區域用於手勢偵測（從上滑動喚出系統 UI），App 無法接收該區域的觸控事件。

### 鍵盤彈出導致 UI 設定失效

- **原因**：Android 在鍵盤開啟時會暫時強制顯示系統 UI，關閉後不會自動恢復原本設定。
- **解法**：
  - 鍵盤關閉後，延遲一段時間再呼叫：
    ```dart
    WidgetsBinding.instance.addPostFrameCallback((_) {
        SystemChrome.restoreSystemUIOverlays();
    });
    ```
    
