那麼,你究竟**如何**將一個為傳統移動裝置設計的應用,使其在各種裝置上都表現出色?需要哪些步驟?

谷歌工程師在處理大型應用方面經驗豐富,他們推薦以下三步法。

步驟 1:抽象化

#

Step 1: Abstract info common to any UI widget

首先,識別你計劃使其動態化的元件。分析這些元件的建構函式,並抽象出可以共享的資料。

需要自適應的常見元件有:

  • 對話方塊,包括全屏和模態對話方塊
  • 導航 UI,包括導航欄和底部欄
  • 自定義佈局,例如“UI 區域是更高還是更寬?”

例如,在 `Dialog` 元件中,你可以共享包含對話方塊**內容**的資訊。

或者,你可能希望在應用視窗較小時切換到 `NavigationBar`,在應用視窗較大時切換到 `NavigationRail`。這些元件可能會共享一個可導航目的地的列表。在這種情況下,你可能會建立一個 `Destination` 元件來儲存這些資訊,並指定 `Destination` 既有圖示又有文字標籤。

接下來,你將評估螢幕尺寸,以決定如何顯示你的 UI。

步驟 2:測量

#

Step 2: How to measure screen size

你有兩種方法來確定顯示區域的大小:`MediaQuery` 和 `LayoutBuilder`。

MediaQuery

#

過去,你可能使用 `MediaQuery.of` 來確定裝置螢幕的大小。然而,如今的裝置螢幕尺寸和形狀多種多樣,這種測試可能會產生誤導。

例如,也許你的應用當前在一個大螢幕上佔據一個小視窗。如果你使用 `MediaQuery.of` 方法並得出螢幕很小的結論(而實際上,應用顯示在大螢幕上的一個微小視窗中),並且你將應用鎖定為豎屏模式,這會導致應用的視窗鎖定在螢幕中央,周圍是黑色。這在大螢幕上絕不是理想的 UI。

請記住,`MediaQuery.sizeOf` 返回的是應用整個螢幕的當前大小,而不僅僅是單個元件的大小。

你有兩種方法來測量螢幕空間。你可以使用 `MediaQuery.sizeOf` 或 `LayoutBuilder`,具體取決於你是想要整個應用視窗的大小,還是更區域性的尺寸。

如果你的元件希望全屏顯示,即使應用視窗很小,請使用 `MediaQuery.sizeOf`,以便你可以根據應用視窗本身的大小選擇 UI。在上一節中,你希望根據整個應用視窗的大小行為進行調整,因此會使用 `MediaQuery.sizeOf`。

在 `build` 方法內部請求應用視窗的大小,例如 `MediaQuery.sizeOf(context)`,會導致給定的 `BuildContext` 在 `size` 屬性發生任何變化時重新構建。

LayoutBuilder

#

`LayoutBuilder` 與 `MediaQuery.sizeOf` 實現類似的目標,但有一些區別。

`LayoutBuilder` 不提供應用視窗的大小,而是提供父 `Widget` 的佈局約束。這意味著你可以根據在元件樹中新增 `LayoutBuilder` 的特定位置獲取尺寸資訊。此外,`LayoutBuilder` 返回 `BoxConstraints` 物件而不是 `Size` 物件,因此你將獲得內容的有效寬度和高度範圍(最小值和最大值),而不僅僅是固定大小。這對於自定義元件很有用。

例如,想象一個自定義元件,你希望其尺寸基於專門分配給該元件的空間,而不是整個應用視窗。在這種情況下,請使用 `LayoutBuilder`。

步驟 3:分支

#

Step 3: Branch the code based on the desired UI

此時,你必須決定在選擇顯示哪個版本的 UI 時使用哪些尺寸斷點。例如,[Material 佈局](https://m3.material.io/foundations/layout/applying-layout/window-size-classes)指南建議對於寬度小於 600 邏輯畫素的視窗使用底部導航欄,對於寬度等於或大於 600 畫素的視窗使用導航軌。再次強調,你的選擇不應取決於裝置的**型別**,而應取決於裝置的可用視窗大小。

要透過一個在 `NavigationRail` 和 `NavigationBar` 之間切換的示例,請檢視 [使用 Material 3 構建動畫自適應應用佈局](https://codelabs.developers.google.com/codelabs/flutter-animated-responsive-layout)。

下一頁討論如何確保你的應用在大螢幕和可摺疊裝置上看起來最佳。