柔軟なウィジェット レイアウトを提供する

このページでは、ウィジェットのサイズ変更と柔軟性の向上について説明します。 Android 12(API レベル 31)で導入されました。また、kubectl の ウィジェットのサイズを決定します

改良された 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 が追加されています。

既存の minWidthminHeightminResizeWidthminResizeHeight 属性に加えて、次の新しい appwidget-provider 属性を使用します。

  • targetCellWidthtargetCellHeight: ランチャーのグリッドセルの観点で、ウィジェットのターゲット サイズを定義します。定義されている場合は、minWidthminHeight の代わりにこれらの属性が使用されます。

  • maxResizeWidth および maxResizeHeight: ランチャーでユーザーがウィジェットのサイズを変更できる最大サイズを定義します。

次の 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 は、160 dp(minResizeWidth)× 110 dp(minResizeHeight)から 160 dp × 199 dp(次のカットオフ ポイント - 1 dp)までサポートしています。
  • tallView は、160 dp × 200 dp ~ 214 dp(次のカットオフ ポイント - 1)× をサポートします。 200 dp。
  • wideView は、215 dp × 110 dp(minResizeHeight)から 250 dp(maxResizeWidth)× 200 dp(maxResizeHeight)までサポートしています。

ウィジェットは、minResizeWidth × minResizeHeightmaxResizeWidth × maxResizeHeight のサイズ範囲をサポートする必要があります。この範囲内で レイアウトを切り替えるカットオフ ポイントを決定できます。

レスポンシブ レイアウトの例
図 1. レスポンシブ レイアウトの例。

正確なレイアウトを提供する

少数のレスポンシブ レイアウトを提供できない場合は、ウィジェットを表示するサイズに合わせてさまざまなレイアウトを提供できます。これは通常、スマートフォン用の 2 つのサイズ(縦向きと横向き)と、折りたたみ式デバイス用の 4 つのサイズで構成されます。

このソリューションを実装するには、アプリで次の手順を行う必要があります。

  1. サイズセットが変更されたときに呼び出される AppWidgetProvider.onAppWidgetOptionsChanged() をオーバーロードします。

  2. サイズを含む Bundle を返す AppWidgetManager.getAppWidgetOptions() を呼び出します。

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

ウィジェットのサイズを決定する

各ウィジェットでデバイスの targetCellWidthtargetCellHeight を定義する必要があります。 Android 12 以降、またはすべての minWidthminHeight 最小使用容量(最小使用容量) できます。ただし、ユーザーがウィジェットをホーム画面に追加すると、通常は指定した最小の幅と高さより大きいスペースが占有されます。

Android のホーム画面には、ウィジェットやアイコンを配置可能なスペースのグリッドがユーザーに表示されます。このグリッドはデバイスによって異なります。たとえば、多くのスマートフォンに表示されるグリッドは 5×4、タブレットに表示されるグリッドはそれより大きい 8×7 です。ウィジェットが追加されると、Android 12 以降を搭載したデバイスでは targetCellWidthtargetCellHeight の制約を満たすために必要な最小限の数のセルを占有するように、グリッドが縦方向と横方向に引き伸ばされます。Android 11(API レベル 30)以前を搭載したデバイスでは、minWidthminHeight の制約を満たすために必要な最小限の数のセルを占有するように、グリッドが縦方向と横方向に引き伸ばされます。

セルの幅と高さ、およびウィジェットに適用される自動マージンのサイズは、デバイスによって異なる場合があります。次の表を使用しておおまかに見積もります。 典型的な 5x4 グリッドのハンドセットにおけるウィジェットの最小寸法は、 占有するグリッドセルの数:

セルの数(幅 x 高さ) 縦向きモードで使用可能なサイズ(dp) 横表示で使用可能なサイズ(dp)
1x1 57x102dp 127x51dp
2×1 130x102dp 269x51dp
3×1 203x102 dp 412x51dp
4x1 276x102dp 554x51dp
5x1 349x102 dp 697x51dp
5x2 349x220dp 697x117dp
5×3 349x337 dp 697x184dp
5x4 349x455 dp 697x250dp
... ... ...
n×m (73n - 16) x (118m - 16) (142n - 15)x(66m - 15)

ポートレート モードのセルサイズを使用して、 minWidthminResizeWidthmaxResizeWidth の各属性。同様に、横向きモードのセルサイズを使用して、minHeightminResizeHeightmaxResizeHeight の各属性に指定する値を指定します。

これは、通常、ポートレート モードではセル幅が小さくなるためです。 セルの高さは通常、横表示よりも高くなります。 横表示は縦表示よりも小さくなります

たとえば、Google Pixel 4 でウィジェットの幅を 1 つのセルまでサイズ変更できるようにするには、minResizeWidth を最大 56 dp に設定して、minResizeWidth 属性の値が 57 dp より小さくなるようにする必要があります。これは、縦向きのセルの幅が 57 dp 以上であるためです。同様に、画面上の 1 つのセルでウィジェットの高さをサイズ変更可能にする場合は、 同じデバイスの場合、minResizeHeight を 50 dp 以下に設定して、 minResizeHeight 属性の値が次の値より小さい 51 dp - 横表示の場合、1 つのセルの高さが 51 dp 以上であるため。

各ウィジェットは、 minResizeWidth/minResizeHeightmaxResizeWidth/maxResizeHeight 属性があるため、それらの間の任意のサイズ範囲に適応する必要があります。

たとえば、プレースメントでウィジェットのデフォルトサイズを設定するには、次の属性を設定します。

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

つまり、ウィジェットのデフォルト サイズは 3x2 セルです。これは targetCellWidth 属性と targetCellHeight 属性、または 180 × 110 dp( (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 グリッドです。
  • セルの数と dps で使用可能なサイズのマッピングは、このページの最小サイズの推定値を示す表に従います。
  • ウィジェットは、そのサイズ範囲に適応します。

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)まで使用されます。同様に、 270x110 dp ~ 270x279 dp の R.layout.widget_weather_forecast_medium が使用されます。 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

<ph type="x-smartling-placeholder">
</ph> 5x2 の「中」サイズの天気ウィジェットの例。このようにウィジェットのサイズを変更すると、横方向のスペースを広げるために 1 セル分伸ばされる点を除き、以前のサイズと同じ UI になります。
図 4.5x2 R.layout.widget_weather_forecast_medium

5x3 の「large」の天気ウィジェットの例指定します。ウィジェットのサイズを変更する
            以前のウィジェットサイズと同じ
UI を基盤にしています
            天気予報を表示するビューをウィジェット内に追加します
            表示されます晴れまたは雨の天気と、各日の最高気温と最低気温を示す記号。
図 5. 5x3 R.layout.widget_weather_forecast_large

5x4 の「large」の天気ウィジェットの例指定します。ウィジェットのサイズを変更する
            以前のウィジェットサイズと同じ
UI を基盤にしています
            木曜日と金曜日(および対応する記号)を追加します
            天気の種類、最高気温、最低気温を示します
            。
図 6. 5x4 R.layout.widget_weather_forecast_large