이 페이지에서는 Android 12 (API 수준 31)에 도입된 위젯 크기 조정과 더 높은 유연성에 관해 설명합니다. 또한 위젯 크기를 확인하는 방법을 자세히 설명합니다.
위젯 크기 및 레이아웃에 개선된 API 사용
Android 12 (API 수준 31)부터 다음 섹션에 설명된 대로 다음을 실행하여 더 세분화된 크기 속성과 유연한 레이아웃을 제공할 수 있습니다.
이전 버전의 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
속성을 사용합니다.
targetCellWidth
및targetCellHeight
: 런처 그리드 셀을 기준으로 위젯의 타겟 크기를 정의합니다. 이러한 속성을 정의하면minWidth
나minHeight
대신 사용됩니다.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
는 160dp (minResizeWidth
) × 110dp(minResizeHeight
)에서 160dp × 199dp (다음 컷오프 지점 - 1dp)까지의 크기를 지원합니다.tallView
는 160dp × 200dp~214dp (다음 컷오프 지점 - 1) × 200dp의 크기를 지원합니다.wideView
는 215dp × 110dp (minResizeHeight
)~250dp(maxResizeWidth
) × 200dp (maxResizeHeight
)의 크기를 지원합니다.
위젯은 minResizeWidth
×minResizeHeight
에서 maxResizeWidth
×maxResizeHeight
까지의 크기 범위를 지원해야 합니다. 이 범위 내에서 컷오프 지점을 결정하여 레이아웃을 전환할 수 있습니다.

정확한 레이아웃 제공
작은 반응형 레이아웃 세트를 만들 수 없다면 위젯이 표시되는 크기에 맞춤설정된 다른 레이아웃을 대신 제공할 수 있습니다. 일반적으로 휴대전화의 경우 두 가지 크기(세로 모드, 가로 모드)이고 폴더블의 경우 네 가지 크기입니다.
이 솔루션을 구현하려면 앱에서 다음 단계를 실행해야 합니다.
크기 세트가 변경될 때 호출되는
AppWidgetProvider.onAppWidgetOptionsChanged()
를 오버로드합니다.크기가 포함된
Bundle
을 반환하는AppWidgetManager.getAppWidgetOptions()
를 호출합니다.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 이상을 실행하는 기기의 경우 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
android:targetCellWidth="3"
android:targetCellHeight="2"
android:minWidth="180dp"
android:minHeight="110dp">
</appwidget-provider>
즉, 위젯의 기본 크기는 targetCellWidth
및 targetCellHeight
속성에서 지정된 3x2 셀이거나 Android 11 이하를 실행하는 기기의 경우 minWidth
및 minHeight
로 지정된 180×110dp입니다. 후자의 경우 셀의 크기는 기기에 따라 다를 수 있습니다.
또한 위젯에 지원되는 크기 범위를 설정하려면 다음 속성을 설정하면 됩니다.
<appwidget-provider
android:minResizeWidth="180dp"
android:minResizeHeight="110dp"
android:maxResizeWidth="530dp"
android:maxResizeHeight="450dp">
</appwidget-provider>
위 속성에 지정된 대로 위젯의 너비는 180dp에서 530dp로, 높이는 110dp에서 450dp로 크기를 조절할 수 있습니다. 그러면 다음 조건이 있는 한 위젯이 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)까지 사용됩니다. 마찬가지로 R.layout.widget_weather_forecast_medium
은 270x110dp에서 270x279dp로 사용되고 R.layout.widget_weather_forecast_large
는 270x280dp에서 530dp (maxResizeWidth
) x 450dp (maxResizeHeight
)로 사용됩니다.
사용자가 위젯의 크기를 조절하면 다음 예와 같이 셀의 각 크기에 맞게 모양이 변경됩니다.

R.layout.widget_weather_forecast_small

R.layout.widget_weather_forecast_medium

R.layout.widget_weather_forecast_medium

R.layout.widget_weather_forecast_large

R.layout.widget_weather_forecast_large