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

本頁將說明 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,可讓您確保小工具在不同螢幕尺寸的裝置上,能更可靠地調整大小。

除了現有 minWidth 之外, minHeightminResizeWidth、 和 minResizeHeight 屬性,請使用以下新 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 到 214dp (下一個截斷點 - 1) × 200dp。
  • wideView 支援從 215 dp × 110 dp (minResizeHeight) 到 250 dp (maxResizeWidth) × 200 dp (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 的格狀版面,而平板電腦則可呈現更大的格狀版面。使用小工具時 並延伸至佔用的儲存格數量下限。 以水平和垂直方向,滿足對 在執行中的裝置上,targetCellWidthtargetCellHeight Android 12 以上版本,或搭載 minWidthminHeight 的限制 搭載 Android 11 (API 級別 30) 以下版本的裝置。

儲存格的寬度和高度,以及套用的自動邊界大小 提供的小工具會因裝置而異請參考下表,根據所需佔用格狀單元的數量,粗略估算小工具在典型 5x4 格狀手機上的最小尺寸:

儲存格數量 (寬 x 高) 直向模式的可用大小 (dp) 橫向模式的可用大小 (dp)
1x1 57x102dp 127x51dp
2x1 130x102dp 269x51dp
3x1 203x102dp 412x51dp
4x1 276x102dp 554x51dp
5x1 349x102dp 697x51dp
5x2 349x220dp 697x117dp
5x3 349x337 dp 697x184dp
5 x 4 349x455 dp 697x250dp
... ... ...
n x 公尺 (73n - 16) x (118m - 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>

這表示小工具的預設大小為 3x2 個格,如 targetCellWidthtargetCellHeight 屬性所指定;如果是搭載 Android 11 以下版本的裝置,則大小為 180×110dp,如 minWidthminHeight 所指定。在後一種情況下,單元格中的大小可能會因裝置而異。

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

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

如同上述屬性所指定,小工具的寬度可從 180dp 調整至 530dp,高度則可從 110dp 調整至 450dp。只要符合下列條件,小工具就能從 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 使用範圍為 180 dp (minResizeWidth) x 110 dp (minResizeHeight) 到 269x279 dp (下一個截斷點 - 1)。同樣地 R.layout.widget_weather_forecast_medium 使用從 270x110 dp 到 270x279dp, 而 R.layout.widget_weather_forecast_large 則使用 270x280 dp 530 dp (maxResizeWidth) x 450 dp (maxResizeHeight)。

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

最小 3x2 格狀空間的天氣小工具範例。UI 顯示
            位置名稱 (東京)、溫度 (14°),以及表示位置的符號
            天氣局部多雲。
圖 2. 3x2 R.layout.widget_weather_forecast_small

4x2 的「中型」天氣小工具範例。以這種方式調整小工具大小時,系統會根據先前的小工具大小建立所有 UI,並新增「多雲」標籤和下午 4 點至 7 點的溫度預測資訊。
圖 3 4x2 R.layout.widget_weather_forecast_medium

5x2 的「中型」天氣小工具範例。以這種方式調整小工具大小,會產生與先前大小相同的 UI,但會延長一個格子的長度,以便佔用更多水平空間。
圖 4.5 x 2 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