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

本頁說明 Android 12 (API 級別 31) 中引入的小工具尺寸調整功能及更豐富的彈性。以及如何決定小工具的大小

針對小工具大小和版面配置使用改良版 API

從 Android 12 (API 級別 31) 開始,您可以按照下列步驟提供更精細的大小屬性和彈性版面配置,如後續章節所述:

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

  2. 提供回應式版面配置確切的版面配置

在舊版 Android 中,您可以使用 OPTION_APPWIDGET_MIN_WIDTHOPTION_APPWIDGET_MIN_HEIGHTOPTION_APPWIDGET_MAX_WIDTHOPTION_APPWIDGET_MAX_HEIGHT 額外項目取得小工具的大小範圍,然後估算小工具的大小,但該邏輯並非在所有情況下都能正常運作。針對指定 Android 12 以上版本的小工具,建議您提供回應式確切版面配置

指定其他小工具大小限制

Android 12 新增了 API,可讓您針對各種螢幕大小,為各種裝置提供更可靠的小工具大小。

除了現有的 minWidthminHeightminResizeWidthminResizeHeight 屬性之外,請使用下列新的 appwidget-provider 屬性:

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

<appwidget-provider
  ...
  android:targetCellWidth="3"
  android:targetCellHeight="2"
  android:maxResizeWidth="250dp"
  android:maxResizeHeight="110dp">
</appwidget-provider>

提供回應式版面配置

如需根據小工具的大小變更版面配置,建議您建立一小組版面配置,每個版面配置適用於不同大小。如果無法採取這個做法,另一個選項則是根據執行階段的確切小工具大小提供版面配置,如本頁所述。

這項功能可讓系統更順暢地調度資源,並提升整體系統健康狀態,因為系統每次以不同大小顯示小工具時,都不必喚醒應用程式。

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

Kotlin

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

    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)
}

Java

@Override
public void onUpdate(...) {
    RemoteViews smallView = ...;
    RemoteViews tallView = ...;
    RemoteViews wideView = ...;

    Map<SizeF, RemoteViews> viewMapping = new ArrayMap<>();
    viewMapping.put(new SizeF(150f, 100f), smallView);
    viewMapping.put(new SizeF(150f, 200f), tallView);
    viewMapping.put(new SizeF(215f, 100f), wideView);
    RemoteViews remoteViews = new RemoteViews(viewMapping);

    appWidgetManager.updateAppWidget(id, remoteViews);
}

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

<appwidget-provider
    android:minResizeWidth="160dp"
    android:minResizeHeight="110dp"
    android:maxResizeWidth="250dp"
    android:maxResizeHeight="200dp">
</appwidget-provider>

上述程式碼片段代表的意義如下:

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

小工具必須支援介於 minResizeWidth × minResizeHeightmaxResizeWidth × maxResizeHeight 的大小範圍。在這個範圍內,您可以決定要切換版面配置的截斷點。

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

提供確切的版面配置

如果一小部分的回應式版面配置不適用,您可以改為針對小工具顯示的大小,提供不同的版面配置。這類裝置通常有兩種尺寸 (直向和橫向模式),而折疊式裝置則為四種尺寸。

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

  1. 在一組大小變更時呼叫 AppWidgetProvider.onAppWidgetOptionsChanged()

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

  3. Bundle 存取 AppWidgetManager.OPTION_APPWIDGET_SIZES 鍵。

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

Kotlin

override fun onAppWidgetOptionsChanged(
        context: Context,
        appWidgetManager: AppWidgetManager,
        id: Int,
        newOptions: Bundle?
) {
    super.onAppWidgetOptionsChanged(context, appWidgetManager, id, newOptions)
    // Get the new sizes.
    val sizes = newOptions?.getParcelableArrayList<SizeF>(
            AppWidgetManager.OPTION_APPWIDGET_SIZES
    )
    // 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 { }

Java

@Override
public void onAppWidgetOptionsChanged(
    Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions) {
    super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions);
    // Get the new sizes.
    ArrayList<SizeF> sizes =
        newOptions.getParcelableArrayList(AppWidgetManager.OPTION_APPWIDGET_SIZES);
    // Check that the list of sizes is provided by the launcher.
    if (sizes == null || sizes.isEmpty()) {
      return;
    }
    // Map the sizes to the RemoteViews that you want.
    Map<SizeF, RemoteViews> viewMapping = new ArrayMap<>();
    for (SizeF size : sizes) {
        viewMapping.put(size, createRemoteViews(size));
    }
    RemoteViews remoteViews = new RemoteViews(viewMapping);
    appWidgetManager.updateAppWidget(id, remoteViews);
}

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

決定小工具的大小

每個小工具都必須為搭載 Android 12 以上版本的裝置定義 targetCellWidthtargetCellHeight,針對所有 Android 版本定義 minWidthminHeight,表示預設使用的空間下限。不過,當使用者在主畫面中新增小工具時,系統通常會佔據您指定的最小寬度和高度。

Android 主畫面會以格狀檢視畫面呈現可用空間,方便使用者在其中放置小工具和圖示。網格可能因裝置而異;例如,許多手機提供 5x4 的格狀空間,平板電腦則可提供更大的格狀。新增小工具後,系統會進行延展,填滿儲存格數量下限 (水平和垂直),在搭載 Android 12 以上版本的裝置上,達到 targetCellWidthtargetCellHeight 的限制。在搭載 Android 11 (API 級別 30) 以下版本的裝置上,則為 minWidthminHeight 限制條件。

儲存格的寬度和高度,以及套用至小工具的自動邊界大小可能因裝置而異。請使用下表,根據您所需要的格線儲存格數量,以一般 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 (118 分鐘 - 16) (142n - 15) x (66 分鐘 - 15)

請使用直向模式儲存格大小,告知您為 minWidthminResizeWidthmaxResizeWidth 屬性提供的值。同樣地,您也可以使用橫向模式儲存格大小,告知您為 minHeightminResizeHeightmaxResizeHeight 屬性提供的值。

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

舉例來說,如果您想在 Google Pixel 4 上將小工具寬度調整為單一儲存格,請將 minResizeWidth 設為最多 56dp,以確保 minResizeWidth 屬性的值小於 57dp,因為儲存格的直向寬度至少為 57dp。同樣地,如果您想在同一裝置的某個儲存格中調整小工具高度,必須將 minResizeHeight 設為最多 50dp,以確保 minResizeHeight 屬性的值小於 51dp,因為在橫向模式下,其中一個儲存格的高度至少為 51dp。

每個小工具都可以在 minResizeWidth/minResizeHeightmaxResizeWidth/maxResizeHeight 屬性之間的大小範圍內調整大小,因此必須配合兩者之間的任何大小範圍進行調整。

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

<appwidget-provider
    android:targetCellWidth="3"
    android:targetCellHeight="2"
    android:minWidth="180dp"
    android:minHeight="110dp">
</appwidget-provider>

也就是說,根據 targetCellWidthtargetCellHeight 屬性指定,小工具的預設大小為 3x2 儲存格,或 180×110dp,如 minWidthminHeight 所指定,搭載 Android 11 以下版本的裝置。如果是後者,儲存格中的大小會因裝置而異。

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

<appwidget-provider
    android:minResizeWidth="180dp"
    android:minResizeHeight="110dp"
    android:maxResizeWidth="530dp"
    android:maxResizeHeight="450dp">
</appwidget-provider>

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

  • 裝置有 5x4 的方格。
  • 儲存格數量與可用大小 (以 dp 為單位) 的對應關係遵循本頁的最小維度估算結果
  • 小工具會配合該大小範圍進行調整。

Kotlin

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))

Java

RemoteViews smallView = 
    new RemoteViews(context.getPackageName(), R.layout.widget_weather_forecast_small);
RemoteViews mediumView = 
    new RemoteViews(context.getPackageName(), R.layout.widget_weather_forecast_medium);
RemoteViews largeView = 
    new RemoteViews(context.getPackageName(), R.layout.widget_weather_forecast_large);

Map<SizeF, RemoteViews> viewMapping = new ArrayMap<>();
viewMapping.put(new SizeF(180f, 110f), smallView);
viewMapping.put(new SizeF(270f, 110f), mediumView);
viewMapping.put(new SizeF(270f, 280f), largeView);
RemoteViews remoteViews = new RemoteViews(viewMapping);

appWidgetManager.updateAppWidget(id, remoteViews);

假設小工具使用上述程式碼片段中定義的回應式版面配置。也就是說,指定為 R.layout.widget_weather_forecast_small 的版面配置會使用 180dp (minResizeWidth) x 110dp (minResizeHeight) 到 269x279dp (下一個截止點 - 1)。同樣地,R.layout.widget_weather_forecast_medium 使用範圍從 270x110 dp 到 270x279 dp,R.layout.widget_weather_forecast_large 則用於 270x280 dp 到 530dp (maxResizeWidth) x 450dp (maxResizeHeight)。

當使用者調整小工具大小時,外觀會隨儲存格的大小而改變,如以下範例所示。

範例:以 3x2 方格尺寸最小的天氣小工具。使用者介面會顯示位置名稱 (東京)、溫度 (14°),以及表示部分天氣不佳的符號。
圖 2. 3x2 R.layout.widget_weather_forecast_small

以 4x2「中」尺寸顯示天氣小工具的範例。以這種方式調整小工具大小時,會以先前的小工具大小為依據,並新增「最多雲」標籤,並新增「最多雲」標籤,以及下午 4 點到晚上 7 點的氣溫預測。
圖 3 4x2 R.layout.widget_weather_forecast_medium

以 5x2「中」尺寸顯示天氣小工具的範例。以這種方式調整小工具大小,將產生與先前大小相同的使用者介面,只不過會延伸一個儲存格長度,以佔用更多水平空間。
圖 4:5x2 R.layout.widget_weather_forecast_medium

以 5x3「大」尺寸顯示的天氣小工具範例。以這種方式調整小工具大小時,會以先前小工具大小的所有使用者介面為基礎,並在小工具中加入一個檢視畫面,提供週二和週三的天氣預報。表示每天晴天或多雨,以及高溫和低溫的符號。
圖 5 5x3 R.layout.widget_weather_forecast_large

範例:以 5x4 大尺寸呈現的天氣小工具。以這種方式調整小工具大小時,會以先前小工具大小的所有使用者介面為基礎,並新增星期四和星期五 (以及代表天氣類型以及每日高溫和低溫的對應符號)。
圖 6:5x4 R.layout.widget_weather_forecast_large