視窗大小類別是一組自主的可視區域中斷點,有助於設計、開發及測試回應式/自動調整式版面配置。中斷點可輕鬆針對獨特的情境最佳化應用程式,讓版面配置保持簡單。
視窗大小類別會將應用程式的可用顯示區域分類為「精簡」、「中等」及「展開」。可用的寬度和高度會另外分類,因此應用程式在任何時間點都會有兩種視窗大小類別:寬度類別和高度類別。一般來說,可用寬度比可用高度更重要,這是因為直向捲動操作比較常見,因此寬度的視窗大小類別可能會與應用程式 UI 設定更相關。
如圖所示,中斷點可讓您繼續思考裝置和設定的版面配置。每個大小類別中斷點都代表了典型裝置情境的大部分案例,當您考慮設計以中斷點為基礎的版面配置時,這個參考框架便可以派上用場。
大小類別 | 中斷點 | 裝置佔比 |
---|---|---|
精簡寬度 | 寬度 < 600 dp | 99.96% 直向模式的手機 |
中等寬度 | 600 dp ≤ 寬度 < 840 dp | 93.73% 直向模式的平板電腦、 直向模式下大部分未摺疊的大型內螢幕 |
展開寬度 | 寬度 ≥ 840 dp | 97.22% 橫向模式的平板電腦、 大多數橫向未摺疊的大型內螢幕 |
精簡高度 | 高度 < 480 dp | 99.78% 橫向模式的手機 |
中等高度 | 480 dp ≤ 高度 < 900 dp | 96.56% 橫向模式的平板電腦、 97.59% 直向模式的手機 |
展開高度 | 高度 ≥ 900 dp | 94.25% 直向模式的平板電腦 |
雖然以實體裝置呈現大小類別相當實用,但視窗大小類別並非明確取決於裝置螢幕大小。視窗大小類別不適用「isTablet」類型的邏輯。視窗大小類別取決於應用程式可用的視窗大小,且無論執行應用程式的裝置類型為何,這都有兩項重要影響:
實體裝置不能保證特定的視窗大小類別。由於許多原因,應用程式能使用的螢幕空間可能不同於裝置螢幕大小。在行動裝置上,分割畫面模式可將畫面分割至兩個應用程式。在 ChromeOS 中,Android 應用程式會顯示在可自由調整大小的任意形式視窗中。折疊式裝置可能會因為裝置折疊或未折疊,而分別存取兩種不同大小的螢幕。
視窗大小類別可能在應用程式的生命週期發生變化。執行應用程式時,變更裝置螢幕方向、進行多工處理和處於摺疊/未摺疊狀態等因素,都會影響可用的螢幕空間大小。因此,視窗大小類別會動態變化,應用程式的 UI 應據此調整。
視窗大小類別可對應至質感設計版面配置指南中的精簡、中等和展開中斷點。請使用視窗大小類別決定概略的應用程式版面配置,例如決定是否使用特定標準版面配置來善用額外的螢幕空間。
您可以使用 Jetpack WindowsManager 程式庫提供的 WindowSizeClass#compute()
函式計算目前的 WindowSizeClass
。以下範例說明如何計算視窗大小類別,並在視窗大小類別變更時接收更新:
Kotlin
class MainActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // ... // Replace with a known container that you can safely add a // view to where the view won't affect the layout and the view // won't be replaced. val container: ViewGroup = binding.container // Add a utility view to the container to hook into // View.onConfigurationChanged(). This is required for all // activities, even those that don't handle configuration // changes. You can't use Activity.onConfigurationChanged(), // since there are situations where that won't be called when // the configuration changes. View.onConfigurationChanged() is // called in those scenarios. container.addView(object : View(this) { override fun onConfigurationChanged(newConfig: Configuration?) { super.onConfigurationChanged(newConfig) computeWindowSizeClasses() } }) computeWindowSizeClasses() } private fun computeWindowSizeClasses() { val metrics = WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(this) val width = metrics.bounds.width() val height = metrics.bounds.height() val density = resources.displayMetrics.density val windowSizeClass = WindowSizeClass.compute(width/density, height/density) // COMPACT, MEDIUM, or EXPANDED val widthWindowSizeClass = windowSizeClass.windowWidthSizeClass // COMPACT, MEDIUM, or EXPANDED val heightWindowSizeClass = windowSizeClass.windowHeightSizeClass // Use widthWindowSizeClass and heightWindowSizeClass. } }
Java
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // ... // Replace with a known container that you can safely add a // view to where the view won't affect the layout and the view // won't be replaced. ViewGroup container = binding.container; // Add a utility view to the container to hook into // View.onConfigurationChanged(). This is required for all // activities, even those that don't handle configuration // changes. You can't use Activity.onConfigurationChanged(), // since there are situations where that won't be called when // the configuration changes. View.onConfigurationChanged() is // called in those scenarios. container.addView(new View(this) { @Override protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); computeWindowSizeClasses(); } }); computeWindowSizeClasses(); } private void computeWindowSizeClasses() { WindowMetrics metrics = WindowMetricsCalculator.getOrCreate() .computeCurrentWindowMetrics(this); int width = metrics.getBounds().width int height = metrics.getBounds().height() float density = getResources().getDisplayMetrics().density; WindowSizeClass windowSizeClass = WindowSizeClass.compute(width/density, height/density) // COMPACT, MEDIUM, or EXPANDED WindowWidthSizeClass widthWindowSizeClass = windowSizeClass.getWindowWidthSizeClass() // COMPACT, MEDIUM, or EXPANDED WindowHeightSizeClass heightWindowSizeClass = windowSizeClass.getWindowHeightSizeClass() // Use widthWindowSizeClass and heightWindowSizeClass. } }
測試視窗大小類別
變更版面配置時,請測試所有視窗大小的版面配置行為,尤其是精簡、中等和展開中斷點寬度。
如果現有版面配置適用於精簡螢幕,請先針對展開寬度大小類別將版面配置最佳化,因為這個大小類別能為其他內容和 UI 變更提供最多空間。接下來,再決定哪種版面配置適合中等寬度大小類別;建議您新增專門的版面配置。
後續步驟
如要進一步瞭解如何使用視窗大小類別建立回應式/自動調整式版面配置,請參閱以下資源:
以 Compose 為基礎的版面配置:支援不同的螢幕大小
以檢視畫面為基礎的版面配置:使用檢視區塊打造回應式/自動調整設計
如要進一步瞭解如何讓應用程式在所有裝置和螢幕大小上提供良好體驗,請參閱: