提供彈性的小工具版面配置

試試 Compose
Jetpack Compose 是 Android 推薦的 UI 工具包。瞭解如何使用 Compose 樣式的 API 建構小工具。

本頁說明 Android 12 (API 級別 31) 針對小工具大小調整功能所做的改良,以及更靈活的設計。此外,也詳細說明如何決定小工具的大小。

使用改良版 API 調整小工具大小和版面配置

自 Android 12 (API 級別 31) 起,您可以按照下列各節所述,提供更精細的大小屬性和彈性版面配置:

  1. 指定其他小工具大小限制。

  2. 提供回應式版面配置或精確版面配置。

在先前的 Android 版本中,可以使用 OPTION_APPWIDGET_MIN_WIDTH、OPTION_APPWIDGET_MIN_HEIGHT、OPTION_APPWIDGET_MAX_WIDTH 和 OPTION_APPWIDGET_MAX_HEIGHT 額外項目取得小工具的大小範圍,然後估算小工具的大小,但該邏輯不適用於所有情況。如果小工具指定 Android 12 以上版本,建議提供回應式或精確版面配置。

指定其他小工具大小限制

Android 12 新增了 API,可確保小工具在不同螢幕大小的裝置上,都能以更可靠的方式調整大小。

除了現有的 minWidth、minHeight、minResizeWidth 和 minResizeHeight 屬性外,請使用下列新的 appwidget-provider 屬性:

以下 XML 說明如何使用大小屬性。

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
  android:targetCellWidth="3"
  android:targetCellHeight="2"
  android:maxResizeWidth="250dp"
  android:maxResizeHeight="110dp">
</appwidget-provider>

提供回應式版面配置

如果版面配置需要根據小工具的大小變更,建議您建立一組小型版面配置,每個版面配置都適用於特定大小範圍。如果不可行,另一個選項是根據執行階段的確切小工具大小提供版面配置,如本頁所述。

這項功能可讓縮放更流暢,並提升整體系統健康度,因為系統不必在每次以不同大小顯示小工具時喚醒應用程式。

以下程式碼範例說明如何提供版面配置清單。

override fun onUpdate(
    /* ... */
) {
    val smallView = RemoteViews(
        /* ... */
    )
    val tallView = RemoteViews(
        /* ... */
    )
    val wideView = RemoteViews(
        /* ... */
    )

    val viewMapping: Map<SizeF, RemoteViews> = mapOf(
        SizeF(150f, 100f) to smallView,
        SizeF(150f, 200f) to tallView,
        SizeF(215f, 100f) to wideView
    )
    val remoteViews = RemoteViews(viewMapping)

    appWidgetManager.updateAppWidget(id, remoteViews)
}

假設小工具具有下列屬性:

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:minResizeWidth="160dp"
    android:minResizeHeight="110dp"
    android:maxResizeWidth="250dp"
    android:maxResizeHeight="200dp">
</appwidget-provider>

上述程式碼片段代表:

  • smallView 支援 160dp (minResizeWidth) × 110dp (minResizeHeight) 到 160dp × 199dp (下一個切點 - 1dp)。
  • tallView 支援 160 dp × 200 dp 到 214 dp (下一個切點 - 1) × 200 dp。
  • wideView 支援 215dp × 110dp (minResizeHeight) 到 250dp (maxResizeWidth) × 200dp (maxResizeHeight)。

小工具必須支援 minResizeWidth × minResizeHeight 到 maxResizeWidth × maxResizeHeight 的大小範圍。在這個範圍內,您可以決定切換版面配置的截止點。

回應式版面配置範例
圖 1 回應式版面配置示例。

提供確切的版面配置

如果無法使用一小組回應式版面配置,您可以根據小工具顯示的大小,提供不同的版面配置。通常手機有兩種大小 (直向和橫向模式),折疊式裝置則有四種大小。

如要導入這項解決方案,應用程式必須執行下列步驟:

  1. 超載 AppWidgetProvider.onAppWidgetOptionsChanged(),系統會在大小組合變更時呼叫。

  2. 呼叫 AppWidgetManager.getAppWidgetOptions(),傳回包含大小的 Bundle。

  3. 從 Bundle 存取 AppWidgetManager.OPTION_APPWIDGET_SIZES 鍵。

以下程式碼範例說明如何提供確切版面配置。

override fun onAppWidgetOptionsChanged(
    context: Context,
    appWidgetManager: AppWidgetManager,
    id: Int,
    newOptions: Bundle?
) {
    super.onAppWidgetOptionsChanged(context, appWidgetManager, id, newOptions)
    // Get the new sizes.
    val sizes = newOptions?.let {
        BundleCompat.getParcelableArrayList(
            it,
            AppWidgetManager.OPTION_APPWIDGET_SIZES,
            SizeF::class.java
        )
    }
    // Check that the list of sizes is provided by the launcher.
    if (sizes.isNullOrEmpty()) {
        return
    }
    // Map the sizes to the RemoteViews that you want.
    val remoteViews = RemoteViews(sizes.associateWith(::createRemoteViews))
    appWidgetManager.updateAppWidget(id, remoteViews)
}

// Create the RemoteViews for the given size.
private fun createRemoteViews(size: SizeF): RemoteViews {
}

決定小工具的大小

每個小工具都必須為搭載 Android 12 以上版本的裝置定義 targetCellWidth 和 targetCellHeight,或為所有 Android 版本定義 minWidth 和 minHeight,指出預設占用的最小空間。不過,當使用者將小工具新增至主畫面時,通常會佔用超過您指定的最小寬度和高度。

Android 主畫面提供使用者可用的空間格線,讓他們放置小工具和圖示。這個格線可能因裝置而異,例如許多手機提供 5x4 格線,平板電腦則可提供更大的格線。新增小工具時,系統會將其水平和垂直拉伸,以佔用最少的儲存格數量,滿足搭載 Android 12 以上版本的裝置上 targetCellWidth 和 targetCellHeight 的限制,或搭載 Android 11 (API 級別 30) 以下版本的裝置上 minWidth 和 minHeight 的限制。

儲存格尺寸和自動邊界會因裝置而異。請根據您要占用的網格儲存格數量,使用下表預估小工具在一般 5x4 網格手機上的最小尺寸:

儲存格數量 (寬 x 高) 直向模式下的可用大小 (dp) 橫向模式下的可用大小 (dp)
1x1 57x102dp 127x51dp
2x1 130x102dp 269x51dp
3x1 203x102dp 412x51dp
4x1 276x102dp 554x51dp
5x1 349x102dp 697x51dp
5x2 349x220dp 697x117dp
5x3 349x337dp 697x184dp
5x4 349x455dp 697x250dp
... ... ...
n x m (73n - 16) x (118m - 16) (142n - 15) x (66m - 15)

請使用直向模式儲存格大小,做為 minWidth、minResizeWidth 和 maxResizeWidth 屬性值的參考依據。同樣地,請使用橫向模式儲存格大小,為 minHeight、minResizeHeight 和 maxResizeHeight 屬性提供值。

這是因為直向模式下的儲存格寬度通常小於橫向模式,同樣地,橫向模式下的儲存格高度通常小於直向模式。

舉例來說,如果您希望小工具寬度在 Google Pixel 4 上可縮小至一個儲存格,則必須將 minResizeWidth 設為不超過 56dp,確保 minResizeWidth 屬性的值小於 57dp,因為直向模式下的儲存格寬度至少為 57dp。同樣地,如果您希望在同一部裝置上,小工具高度可在一個儲存格中調整大小,則必須將 minResizeHeight 設為不超過 50dp,確保 minResizeHeight 屬性的值小於 51dp,因為在橫向模式下,一個儲存格的高度至少為 51dp。

每個小工具都可以在 minResizeWidth/minResizeHeight 和 maxResizeWidth/maxResizeHeight 屬性之間的大小範圍內調整大小,也就是說,小工具必須能適應這些屬性之間的任何大小範圍。

舉例來說,如要設定小工具在刊登位置的預設大小,可以設定下列屬性:

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:targetCellWidth="3"
    android:targetCellHeight="2"
    android:minWidth="180dp"
    android:minHeight="110dp">
</appwidget-provider>

這表示小工具的預設大小為 3x2 儲存格 (由 targetCellWidth 和 targetCellHeight 屬性指定),或 180×110dp (由 minWidth 和 minHeight 指定,適用於搭載 Android 11 以下版本的裝置)。在後者的情況下,儲存格大小可能會因裝置而異。

此外,如要設定小工具支援的大小範圍,可以設定下列屬性:

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:minResizeWidth="180dp"
    android:minResizeHeight="110dp"
    android:maxResizeWidth="530dp"
    android:maxResizeHeight="450dp">
</appwidget-provider>

如上述屬性所指定,小工具的寬度可調整為 180dp 至 530dp,高度可調整為 110dp 至 450dp。只要符合下列條件,小工具的大小就能從 3x2 調整為 5x2 儲存格:

  • 裝置採用 5x4 格狀排列。
  • 儲存格數量與可用大小 (以 dp 為單位) 之間的對應關係,請參閱本頁顯示最小尺寸估計值的表格。
  • 小工具會根據該大小範圍進行調整。

val smallView = RemoteViews(context.packageName, R.layout.widget_weather_forecast_small)
val mediumView = RemoteViews(context.packageName, R.layout.widget_weather_forecast_medium)
val largeView = RemoteViews(context.packageName, R.layout.widget_weather_forecast_large)

val viewMapping: Map<SizeF, RemoteViews> = mapOf(
    SizeF(180f, 110f) to smallView,
    SizeF(270f, 110f) to mediumView,
    SizeF(270f, 280f) to largeView
)

appWidgetManager.updateAppWidget(appWidgetId, RemoteViews(viewMapping))

假設小工具使用上述程式碼片段中定義的回應式版面配置。這表示指定為 R.layout.widget_weather_forecast_small 的版面配置會從 180dp (minResizeWidth) x 110dp (minResizeHeight) 使用到 269x279dp (下一個切點 - 1)。同樣地,R.layout.widget_weather_forecast_medium 用於 270x110dp 到 270x279dp,R.layout.widget_weather_forecast_large 用於 270x280dp 到 530dp (maxResizeWidth) x 450dp (maxResizeHeight)。

使用者調整小工具大小時,小工具的外觀會隨之變更,以配合各個儲存格的大小,如以下範例所示。

天氣小工具範例,採用最小的 3x2 格大小。使用者介面會顯示地點名稱 (東京)、溫度 (14°) 和代表多雲的天氣符號。
圖 2. 3x2 R.layout.widget_weather_forecast_small。

4x2「中型」天氣小工具範例。透過這種方式調整小工具大小,會沿用先前小工具大小的所有 UI,並新增「多雲」標籤和下午 4 點到 7 點的氣溫預測。
圖 3 4x2 R.layout.widget_weather_forecast_medium。

5x2「中型」天氣小工具範例。以這種方式調整小工具大小,會產生與先前大小相同的 UI,但會拉長一個儲存格長度,占用更多水平空間。
圖 4:5x2 R.layout.widget_weather_forecast_medium。

5x3「大型」天氣小工具範例。透過這種方式調整小工具大小,會以先前小工具大小的所有 UI 為基礎,並在小工具中新增檢視畫面,其中包含週二和週三的天氣預報。代表晴天或雨天的符號,以及每天的最高和最低溫度。
圖 5 5x3 R.layout.widget_weather_forecast_large。

5x4「大型」天氣小工具範例。透過這種方式調整小工具大小,會沿用先前小工具大小的所有 UI,並新增星期四和星期五 (以及對應的符號,表示天氣類型以及每天的高溫和低溫)。
圖 6:5x4 R.layout.widget_weather_forecast_large。