유연한 위젯 레이아웃 제공

이 페이지에서는 위젯 크기 조정 및 유연성 향상을 위한 개선사항을 설명합니다. 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 속성을 사용합니다.

  • targetCellWidth 드림 및 targetCellHeight: 런처 그리드 셀 측면에서 위젯의 대상 크기를 정의합니다. 이러한 속성을 정의하면 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)
}

자바

@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 그 범위 내에서 컷오프 포인트를 결정하여 레이아웃을 전환할 수 있습니다.

반응형 레이아웃의 예
그림 1. 반응형 레이아웃의 예

정확한 레이아웃 제공

작은 반응형 레이아웃 세트를 만들 수 없다면 위젯이 표시되는 크기에 맞춤설정된 다른 레이아웃을 대신 제공할 수 있습니다. 일반적으로 휴대전화의 경우 두 가지 크기(세로 모드, 가로 모드)이고 폴더블의 경우 네 가지 크기입니다.

이 솔루션을 구현하려면 앱에서 다음 단계를 실행해야 합니다.

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

자바

@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 버전) 기본적으로 제공됩니다 하지만 사용자가 홈 화면에 위젯을 추가하면 일반적으로 지정된 최소 너비 및 높이보다 많은 부분을 차지합니다.

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 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보다 작을 수 있습니다. 마찬가지로 위젯 높이의 크기를 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 속성 또는 180×110dp 다음을 실행하는 기기의 경우 minWidthminHeight에 의해 지정됨 Android 11 이하 후자의 경우 셀의 크기는 기기에 따라 다를 수 있습니다

또한 위젯의 지원되는 크기 범위를 설정하려면 다음을 설정할 수 있습니다. 속성:

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

위 속성으로 지정된 대로 위젯의 너비는 180dp에서 530dp로 크기를 조절할 수 있고, 높이는 110dp에서 450dp로 크기를 조절할 수 있습니다. 그런 다음 위젯의 크기를 3x2 셀에서 5x2 셀로 변경할 수 있습니다. 단, 다음과 같은 조건이 있습니다.

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

자바

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)

사용자가 위젯의 크기를 조절하면 위젯의 모양이 셀에 있는 값을 변경할 수 있습니다.

가장 작은 3x2 그리드 크기의 날씨 위젯 예 UI 표시
            위치 이름 (도쿄), 기온 (14°)과
            대체로 흐린 날씨입니다.
그림 2. 3x2 R.layout.widget_weather_forecast_small

4x2 &#39;중간&#39; 크기의 날씨 위젯 예 있습니다. 위젯 크기 조정
            이렇게 하면 이전 위젯 크기의 모든 UI를 기반으로 빌드됩니다.
            &#39;대체로 흐림&#39;이라는 라벨을 기온을 예보하여
            오후 4시부터 오후 7시까지입니다.
그림 3. 4x2 R.layout.widget_weather_forecast_medium

<ph type="x-smartling-placeholder">
</ph> 5x2 &#39;중간&#39; 크기의 날씨 위젯 예 있습니다. 위젯 크기 조정
            이렇게 하면 크기보다 크다는 점을 제외하면 이전 크기와 UI가
            1 셀 길이만큼 늘어져 더 많은 가로 공간을 차지합니다.
그림 4. 5x2 R.layout.widget_weather_forecast_medium

5x3 &#39;대형&#39;의 날씨 위젯 예 있습니다. 위젯 크기 조정
            이렇게 하면 이전 위젯 크기의 모든 UI를 기반으로 빌드됩니다.
            위젯 내에 날씨 예보가 포함된 뷰를 추가합니다.
            있습니다. 맑거나 비가 오는 날씨를 나타내는 기호
            일일 최고 기온 및 최저 기온을 확인할 수 있습니다.
그림 5. 5x3 R.layout.widget_weather_forecast_large

5x4 &#39;대형&#39;의 날씨 위젯 예 있습니다. 위젯 크기 조정
            이렇게 하면 이전 위젯 크기의 모든 UI를 기반으로 빌드됩니다.
            목요일과 금요일 (및 해당 기호)을
            날씨 유형과 최고 및 최저 기온을 표시할 수 있습니다.
            으로 표시됩니다.
그림 6. 5x4 R.layout.widget_weather_forecast_large