간단한 위젯 만들기

앱 위젯은 홈 화면과 같은 다른 앱에 삽입하여 주기적인 업데이트를 받을 수 있는 소형 앱 뷰입니다. 이러한 뷰를 사용자 인터페이스에서는 위젯이라고 하며, 앱 위젯 제공자 (또는 위젯 제공자)를 사용하여 뷰를 게시할 수 있습니다. 다른 위젯을 포함하는 앱 구성요소를 앱 위젯 호스트 (또는 위젯 호스트)라고 합니다. 그림 1은 샘플 음악 위젯을 보여줍니다.

음악 위젯의 예
그림 1. 음악 위젯의 예

이 문서에서는 위젯 제공자를 사용하여 위젯을 게시하는 방법을 설명합니다. 앱 위젯을 호스팅하는 자체 AppWidgetHost를 만드는 방법에 관한 자세한 내용은 위젯 호스트 빌드를 참고하세요.

위젯을 디자인하는 방법에 관한 자세한 내용은 앱 위젯 개요를 참고하세요.

위젯 구성요소

위젯을 만들려면 다음과 같은 기본 구성요소가 필요합니다.

AppWidgetProviderInfo 객체
위젯의 레이아웃, 업데이트 빈도, AppWidgetProvider 클래스 등 위젯의 메타데이터를 설명합니다. AppWidgetProviderInfo은 이 문서에 설명된 대로 XML로 정의됩니다.
AppWidgetProvider 클래스
프로그래매틱 방식으로 위젯과 상호작용할 수 있는 기본 메서드를 정의합니다. 이를 통해 위젯이 업데이트, 사용 설정, 사용 중지 또는 삭제될 때 브로드캐스트를 수신합니다. 이 문서에 설명된 대로 매니페스트에서 AppWidgetProvider를 선언한 다음 구현합니다.
레이아웃 보기
위젯의 초기 레이아웃을 정의합니다. 레이아웃은 이 문서에 설명된 대로 XML에 정의됩니다.

그림 2는 이러한 구성요소가 전반적인 앱 위젯 처리 흐름에 어떻게 적용되는지 보여줍니다.

앱 위젯 처리 흐름
그림 2. 앱 위젯 처리 흐름

위젯에 사용자 구성이 필요한 경우 앱 위젯 구성 활동을 구현합니다. 이 활동을 통해 사용자는 위젯 설정(예: 시계 위젯의 시간대)을 수정할 수 있습니다.

또한 유연한 위젯 레이아웃, 기타 개선사항, 고급 위젯, 컬렉션 위젯, 위젯 호스트 빌드와 같은 개선사항을 권장합니다.

AppWidgetProviderInfo XML 선언

AppWidgetProviderInfo 객체는 위젯의 필수 특성을 정의합니다. 단일 <appwidget-provider> 요소를 사용하여 XML 리소스 파일에서 AppWidgetProviderInfo 객체를 정의하고 프로젝트의 res/xml/ 폴더에 저장합니다.

예를 들면 다음과 같습니다.

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:minWidth="40dp"
    android:minHeight="40dp"
    android:targetCellWidth="1"
    android:targetCellHeight="1"
    android:maxResizeWidth="250dp"
    android:maxResizeHeight="120dp"
    android:updatePeriodMillis="86400000"
    android:description="@string/example_appwidget_description"
    android:previewLayout="@layout/example_appwidget_preview"
    android:initialLayout="@layout/example_loading_appwidget"
    android:configure="com.example.android.ExampleAppWidgetConfigurationActivity"
    android:resizeMode="horizontal|vertical"
    android:widgetCategory="home_screen"
    android:widgetFeatures="reconfigurable|configuration_optional">
</appwidget-provider>

위젯 크기 조정 속성

기본 홈 화면은 높이와 너비가 정의된 셀의 그리드를 기반으로 창에 위젯을 배치합니다. 대부분의 홈 화면에서는 위젯이 그리드 셀의 정수배인 크기만 사용할 수 있습니다(예: 가로로 2개의 셀, 세로로 세 개의 셀).

위젯 크기 조정 속성을 사용하면 위젯의 기본 크기를 지정하고 위젯 크기의 하한 및 상한을 제공할 수 있습니다. 이 컨텍스트에서 위젯의 기본 크기는 위젯이 처음 홈 화면에 추가될 때 차지하는 크기입니다.

다음 표에서는 위젯 크기 조정과 관련된 <appwidget-provider> 속성을 설명합니다.

속성 및 설명
targetCellWidthtargetCellHeight (Android 12), minWidth, minHeight
  • Android 12부터 targetCellWidthtargetCellHeight 속성이 그리드 셀 측면에서 위젯의 기본 크기를 지정합니다. 이러한 속성은 Android 11 이하에서 무시되며 홈 화면이 그리드 기반 레이아웃을 지원하지 않으면 무시될 수 있습니다.
  • minWidthminHeight 속성은 위젯의 기본 크기를 dp 단위로 지정합니다. 위젯의 최소 너비 또는 높이 값이 셀의 크기와 일치하지 않으면 값이 가장 가까운 셀 크기로 반올림됩니다.
사용자의 기기가 targetCellWidthtargetCellHeight를 지원하지 않는 경우 앱이 minWidthminHeight를 사용하도록 대체할 수 있도록 두 속성 세트(targetCellWidthtargetCellHeight, minWidthminHeight)를 모두 지정하는 것이 좋습니다. 지원되는 경우 targetCellWidthtargetCellHeight 속성이 minWidthminHeight 속성보다 우선합니다.
minResizeWidthminResizeHeight 위젯의 절대 최소 크기를 지정합니다. 이러한 값은 위젯을 읽을 수 없거나 사용할 수 없는 크기를 지정합니다. 이러한 속성을 사용하면 사용자가 위젯의 크기를 기본 위젯 크기보다 작은 크기로 조절할 수 있습니다. minResizeWidth 속성이 minWidth보다 크거나 가로 크기 조절이 사용 설정되지 않은 경우 무시됩니다. resizeMode를 참고하세요. 마찬가지로 minResizeHeight 속성이 minHeight보다 크거나 세로 크기 조절이 사용 설정되지 않은 경우 무시됩니다.
maxResizeWidthmaxResizeHeight 위젯의 권장 최대 크기를 지정합니다. 값이 그리드 셀 크기의 배수가 아니면 가장 가까운 셀 크기로 반올림됩니다. maxResizeWidth 속성이 minWidth보다 작거나 가로 크기 조절이 사용 설정되지 않은 경우 무시됩니다. resizeMode를 참고하세요. 마찬가지로 maxResizeHeight 속성이 minHeight보다 크거나 세로 크기 조절이 사용 설정되지 않은 경우 무시됩니다. Android 12에서 도입되었습니다.
resizeMode 위젯의 크기를 조절할 수 있는 규칙을 지정합니다. 이 속성을 사용하여 홈 화면 위젯의 크기를 가로, 세로 또는 두 축 모두에서 조절할 수 있습니다. 사용자가 위젯을 길게 터치하여 크기 조절 핸들을 표시한 다음 가로 또는 세로 핸들을 드래그하여 레이아웃 그리드에서 크기를 변경합니다. resizeMode 속성 값에는 horizontal, vertical, none가 포함됩니다. 위젯의 크기를 가로와 세로로 조절할 수 있다고 선언하려면 horizontal|vertical를 사용합니다.

위 표의 속성이 위젯 크기 조정에 미치는 영향을 설명하기 위해 다음과 같은 사양이 있다고 가정합니다.

  • 그리드 셀은 너비 30dp, 높이 50dp입니다.
  • 다음과 같은 속성 사양이 제공됩니다.
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:minWidth="80dp"
    android:minHeight="80dp"
    android:targetCellWidth="2"
    android:targetCellHeight="2"
    android:minResizeWidth="40dp"
    android:minResizeHeight="40dp"
    android:maxResizeWidth="120dp"
    android:maxResizeHeight="120dp"
    android:resizeMode="horizontal|vertical" />

Android 12부터:

targetCellWidthtargetCellHeight 속성을 위젯의 기본 크기로 사용합니다.

위젯의 크기는 기본적으로 2x2입니다. 위젯의 크기는 2x1 또는 최대 4x3까지 조정할 수 있습니다.

Android 11 이하:

minWidthminHeight 속성을 사용하여 위젯의 기본 크기를 계산합니다.

기본 너비 = Math.ceil(80 / 30) = 3

기본 높이 = Math.ceil(80 / 50) = 2

위젯의 크기는 기본적으로 3x2입니다. 위젯은 2x1 또는 최대 전체 화면으로 크기를 조절할 수 있습니다.

추가 위젯 속성

다음 표에서는 위젯 크기 조정 이외의 품질과 관련된 <appwidget-provider> 속성을 설명합니다.

속성 및 설명
updatePeriodMillis 위젯 프레임워크가 onUpdate() 콜백 메서드를 호출하여 AppWidgetProvider에서 업데이트를 요청하는 빈도를 정의합니다. 이 값을 사용하면 실제 업데이트가 정확히 제시간에 발생하지 않을 수도 있으며 배터리를 절약하기 위해 업데이트 빈도는 한 시간에 한 번 이하로 가능한 한 자주 업데이트하는 것이 좋습니다. 적절한 업데이트 기간을 선택하기 위한 고려사항의 전체 목록은 위젯 콘텐츠 업데이트를 위한 최적화를 참조하세요.
initialLayout 위젯 레이아웃을 정의하는 레이아웃 리소스를 가리킵니다.
configure 사용자가 위젯을 추가할 때 실행되는 활동을 정의하여 위젯 속성을 구성할 수 있도록 합니다. 사용자가 위젯을 구성하도록 사용 설정을 참고하세요. Android 12부터 앱에서 초기 구성을 건너뛸 수 있습니다. 자세한 내용은 위젯의 기본 구성 사용을 참고하세요.
description 위젯에 표시할 위젯 선택 도구에 대한 설명을 지정합니다. Android 12에서 도입되었습니다.
previewLayout (Android 12) 및 previewImage (Android 11 이하)
  • Android 12부터 previewLayout 속성은 확장 가능한 미리보기를 지정하며, 이 미리보기는 위젯의 기본 크기로 설정된 XML 레이아웃으로 제공됩니다. 이 속성으로 지정된 레이아웃 XML은 실제 기본값이 있는 실제 위젯과 동일한 레이아웃 XML인 것이 이상적입니다.
  • Android 11 이하에서 previewImage 속성은 위젯이 구성된 후 위젯이 어떻게 표시되는지 미리보기를 지정하며, 사용자는 앱 위젯을 선택할 때 이 위젯이 표시됩니다. 이 속성이 제공되지 않으면 사용자에게 앱의 런처 아이콘이 대신 표시됩니다. 이 필드는 AndroidManifest.xml 파일의 <receiver> 요소에 있는 android:previewImage 속성에 상응합니다.
참고: 사용자의 기기가 previewLayout를 지원하지 않는 경우 앱이 previewImage를 사용하도록 대체할 수 있도록 previewImagepreviewLayout 속성을 모두 지정하는 것이 좋습니다. 자세한 내용은 확장 가능한 위젯 미리보기와의 하위 호환성을 참조하세요.
autoAdvanceViewId 위젯의 호스트에서 자동으로 진행하는 위젯 하위 뷰의 뷰 ID를 지정합니다.
widgetCategory 위젯을 홈 화면(home_screen), 잠금 화면 (keyguard) 또는 둘 다에 표시할 수 있는지 선언합니다. Android 5.0 이상에서는 home_screen만 유효합니다.
widgetFeatures 위젯에서 지원하는 기능을 선언합니다. 예를 들어 사용자가 위젯을 추가할 때 위젯이 기본 구성을 사용하도록 하려면 configuration_optionalreconfigurable 플래그를 모두 지정합니다. 이렇게 하면 사용자가 위젯을 추가한 후 구성 활동 실행을 우회할 수 있습니다. 사용자는 나중에 위젯을 재구성할 수 있습니다.

AppWidgetProvider 클래스를 사용하여 위젯 브로드캐스트 처리

AppWidgetProvider 클래스는 위젯 브로드캐스트를 처리하고 위젯 수명 주기 이벤트에 대한 응답으로 위젯을 업데이트합니다. 다음 섹션에서는 매니페스트에서 AppWidgetProvider을 선언하고 구현하는 방법을 설명합니다.

매니페스트에서 위젯 선언

먼저 다음 예와 같이 앱의 AndroidManifest.xml 파일에서 AppWidgetProvider 클래스를 선언합니다.

<receiver android:name="ExampleAppWidgetProvider"
                 android:exported="false">
    <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
    </intent-filter>
    <meta-data android:name="android.appwidget.provider"
               android:resource="@xml/example_appwidget_info" />
</receiver>

<receiver> 요소에는 위젯에 사용되는 AppWidgetProvider를 지정하는 android:name 속성이 필요합니다. 별도의 프로세스를 AppWidgetProvider에 브로드캐스트해야 하는 경우가 아니라면 구성요소를 내보내면 안 됩니다. 일반적으로는 그렇지 않습니다.

<intent-filter> 요소는 android:name 속성이 있는 <action> 요소를 포함해야 합니다. 이 속성은 AppWidgetProviderACTION_APPWIDGET_UPDATE 브로드캐스트를 허용함을 지정합니다. 이 브로드캐스트만 명시적으로 선언하면 됩니다. AppWidgetManager는 필요에 따라 다른 모든 위젯 브로드캐스트를 자동으로 AppWidgetProvider에 전송합니다.

<meta-data> 요소는 AppWidgetProviderInfo 리소스를 지정하며 다음과 같은 속성이 필요합니다.

  • android:name: 메타데이터 이름을 지정합니다. android.appwidget.provider를 사용하여 데이터를 AppWidgetProviderInfo 설명어로 식별합니다.
  • android:resource: AppWidgetProviderInfo 리소스 위치를 지정합니다.

AppWidgetProvider 클래스 구현

AppWidgetProvider 클래스는 위젯 브로드캐스트를 처리하기 위한 편의 클래스로 BroadcastReceiver를 확장합니다. 위젯이 업데이트, 삭제, 사용 설정, 사용 중지될 때와 같이 위젯과 관련된 이벤트 브로드캐스트만 수신합니다. 이러한 브로드캐스트 이벤트가 발생하면 다음과 같은 AppWidgetProvider 메서드가 호출됩니다.

onUpdate()
AppWidgetProviderInfoupdatePeriodMillis 속성으로 정의된 간격으로 위젯을 업데이트하기 위해 호출됩니다. 자세한 내용은 이 페이지의 추가 위젯 속성을 설명하는 표를 참고하세요.
이 메서드는 사용자가 위젯을 추가할 때도 호출되므로 View 객체의 이벤트 핸들러를 정의하거나 위젯에 표시할 데이터를 로드하는 작업을 시작하는 등의 필수 설정을 실행합니다. 그러나 configuration_optional 플래그 없이 구성 활동을 선언하면 이 메서드는 사용자가 위젯을 추가할 때 호출되지 않지만 후속 업데이트에서는 호출됩니다. 구성이 완료될 때 첫 번째 업데이트를 실행하는 것은 구성 활동의 책임입니다. 자세한 내용은 사용자가 앱 위젯을 구성하도록 사용 설정을 참고하세요.
가장 중요한 콜백은 onUpdate()입니다. 자세한 내용은 이 페이지의 onUpdate() 클래스로 이벤트 처리를 참고하세요.
onAppWidgetOptionsChanged()

위젯이 처음 배치될 때와 위젯의 크기가 조절될 때마다 호출됩니다. 이 콜백을 사용하여 위젯의 크기 범위에 따라 콘텐츠를 표시하거나 숨길 수 있습니다. 다음을 포함하는 Bundle를 반환하는 getAppWidgetOptions()를 호출하여 크기 범위(Android 12부터는 위젯 인스턴스가 사용할 수 있는 크기 목록)를 가져옵니다.

onDeleted(Context, int[])

위젯 호스트에서 위젯이 삭제될 때마다 호출됩니다.

onEnabled(Context)

위젯의 인스턴스가 처음 생성될 때 호출됩니다. 예를 들어 사용자가 위젯의 인스턴스 두 개를 추가하는 경우 처음 한 번만 호출됩니다. 새 데이터베이스를 열거나 모든 위젯 인스턴스에 한 번만 실행해야 하는 다른 설정을 실행해야 하는 경우 여기에서 실행하는 것이 좋습니다.

onDisabled(Context)

위젯의 마지막 인스턴스가 위젯 호스트에서 삭제될 때 호출됩니다. 여기에서 임시 데이터베이스 삭제와 같이 onEnabled(Context)에서 실행된 모든 작업을 삭제합니다.

onReceive(Context, Intent)

이는 모든 브로드캐스트와 앞의 각 콜백 메서드 전에 호출됩니다. 일반적으로 이 메서드는 구현할 필요가 없습니다. 기본 AppWidgetProvider 구현은 모든 위젯 브로드캐스트를 필터링하고 이전 메서드를 적절하게 호출하기 때문입니다.

AndroidManifest<receiver> 요소를 사용하여 AppWidgetProvider 클래스 구현을 broadcast receiver로 선언해야 합니다. 자세한 내용은 이 페이지의 매니페스트에서 위젯 선언을 참고하세요.

onUpdate() 클래스로 이벤트 처리

가장 중요한 AppWidgetProvider 콜백은 onUpdate()입니다. configuration_optional 플래그 없이 구성 활동을 사용하지 않는 한 각 위젯이 호스트에 추가될 때 호출되기 때문입니다. 위젯이 사용자 상호작용 이벤트를 허용하는 경우 이 콜백에 이벤트 핸들러를 등록합니다. 위젯이 임시 파일이나 데이터베이스를 만들지 않거나 정리가 필요한 다른 작업을 실행하지 않는 경우 onUpdate()만 정의해야 하는 콜백 메서드가 될 수 있습니다.

예를 들어 탭했을 때 활동을 실행하는 버튼이 있는 위젯을 원하는 경우 다음과 같은 AppWidgetProvider 구현을 사용할 수 있습니다.

Kotlin

class ExampleAppWidgetProvider : AppWidgetProvider() {

    override fun onUpdate(
            context: Context,
            appWidgetManager: AppWidgetManager,
            appWidgetIds: IntArray
    ) {
        // Perform this loop procedure for each widget that belongs to this
        // provider.
        appWidgetIds.forEach { appWidgetId ->
            // Create an Intent to launch ExampleActivity.
            val pendingIntent: PendingIntent = PendingIntent.getActivity(
                    /* context = */ context,
                    /* requestCode = */  0,
                    /* intent = */ Intent(context, ExampleActivity::class.java),
                    /* flags = */ PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
            )

            // Get the layout for the widget and attach an onClick listener to
            // the button.
            val views: RemoteViews = RemoteViews(
                    context.packageName,
                    R.layout.appwidget_provider_layout
            ).apply {
                setOnClickPendingIntent(R.id.button, pendingIntent)
            }

            // Tell the AppWidgetManager to perform an update on the current
            // widget.
            appWidgetManager.updateAppWidget(appWidgetId, views)
        }
    }
}

Java

public class ExampleAppWidgetProvider extends AppWidgetProvider {

    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        // Perform this loop procedure for each widget that belongs to this
        // provider.
        for (int i=0; i < appWidgetIds.length; i++) {
            int appWidgetId = appWidgetIds[i];
            // Create an Intent to launch ExampleActivity
            Intent intent = new Intent(context, ExampleActivity.class);
            PendingIntent pendingIntent = PendingIntent.getActivity(
                /* context = */ context,
                /* requestCode = */ 0,
                /* intent = */ intent,
                /* flags = */ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
            );

            // Get the layout for the widget and attach an onClick listener to
            // the button.
            RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.example_appwidget_layout);
            views.setOnClickPendingIntent(R.id.button, pendingIntent);

            // Tell the AppWidgetManager to perform an update on the current app
            // widget.
            appWidgetManager.updateAppWidget(appWidgetId, views);
        }
    }
}

AppWidgetProvideronUpdate() 메서드만 정의하며, 이 메서드를 사용하여 Activity를 실행하고 setOnClickPendingIntent(int, PendingIntent)를 사용하여 위젯의 버튼에 연결하는 PendingIntent를 만듭니다. 여기에는 이 제공자가 만든 각 위젯을 식별하는 ID 배열인 appWidgetIds의 각 항목을 반복하는 루프가 포함됩니다. 사용자가 위젯 인스턴스를 두 개 이상 만들면 모두 동시에 업데이트됩니다. 그러나 위젯의 모든 인스턴스에 하나의 updatePeriodMillis 일정만 관리됩니다. 예를 들어 업데이트 일정이 2시간마다로 정의되고 위젯의 두 번째 인스턴스가 첫 번째 인스턴스 뒤에 추가된 경우 두 번째 인스턴스는 첫 번째에 정의된 기간에 모두 업데이트되고 두 번째 업데이트 기간은 무시됩니다. 둘 다 1시간이 아니라 2시간마다 업데이트됩니다.

자세한 내용은 ExampleAppWidgetProvider.java 샘플 클래스를 참고하세요.

위젯 브로드캐스트 인텐트 수신

AppWidgetProvider는 편의 클래스입니다. 위젯 브로드캐스트를 직접 수신하려면 자체 BroadcastReceiver를 구현하거나 onReceive(Context,Intent) 콜백을 재정의하면 됩니다. 주의해야 할 인텐트는 다음과 같습니다.

위젯 레이아웃 만들기

위젯의 초기 레이아웃을 XML로 정의하고 프로젝트의 res/layout/ 디렉터리에 저장해야 합니다. 자세한 내용은 디자인 가이드라인을 참고하세요.

레이아웃을 잘 알고 있다면 위젯 레이아웃을 간단하게 만들 수 있습니다. 그러나 위젯 레이아웃은 모든 종류의 레이아웃 또는 뷰 위젯을 지원하지는 않는 RemoteViews에 기반합니다. 맞춤 뷰 또는 RemoteViews에서 지원하는 뷰의 서브클래스는 사용할 수 없습니다.

RemoteViews는 런타임 시 레이아웃 리소스를 느리게 확장하는 데 사용할 수 있는 보이지 않는 제로 크기의 ViewViewStub도 지원합니다.

스테이트풀(Stateful) 동작 지원

Android 12에서는 다음 기존 구성요소를 사용하여 스테이트풀(Stateful) 동작 지원을 추가합니다.

위젯은 여전히 스테이트리스(Stateless)입니다. 앱은 상태를 저장하고 상태 변경 이벤트에 등록해야 합니다.

스테이트풀(Stateful) 동작을 보여주는 쇼핑 목록 위젯의 예
그림 3. 스테이트풀(Stateful) 동작의 예

다음 코드 예는 이러한 구성요소를 구현하는 방법을 보여줍니다.

Kotlin

// Check the view.
remoteView.setCompoundButtonChecked(R.id.my_checkbox, true)

// Check a radio group.
remoteView.setRadioGroupChecked(R.id.my_radio_group, R.id.radio_button_2)

// Listen for check changes. The intent has an extra with the key
// EXTRA_CHECKED that specifies the current checked state of the view.
remoteView.setOnCheckedChangeResponse(
        R.id.my_checkbox,
        RemoteViews.RemoteResponse.fromPendingIntent(onCheckedChangePendingIntent)
)

Java

// Check the view.
remoteView.setCompoundButtonChecked(R.id.my_checkbox, true);

// Check a radio group.
remoteView.setRadioGroupChecked(R.id.my_radio_group, R.id.radio_button_2);

// Listen for check changes. The intent has an extra with the key
// EXTRA_CHECKED that specifies the current checked state of the view.
remoteView.setOnCheckedChangeResponse(
    R.id.my_checkbox,
    RemoteViews.RemoteResponse.fromPendingIntent(onCheckedChangePendingIntent));

두 가지 레이아웃을 제공합니다. 하나는 res/layout-v31에서 Android 12 이상을 실행하는 기기를 타겟팅하고 다른 하나는 기본 res/layout 폴더에서 Android 11 이하를 타겟팅하는 것입니다.

둥근 모서리 구현

Android 12에서는 위젯의 둥근 모서리 반경을 설정하는 다음 시스템 매개변수를 도입합니다.

다음 예는 위젯 모서리에 system_app_widget_background_radius를 사용하고 위젯 내부 뷰에 system_app_widget_inner_radius를 사용하는 위젯을 보여줍니다.

위젯 배경의 반경과 위젯 내부 뷰를 보여주는 위젯
그림 4. 둥근 모서리.

1 위젯의 모서리

2 위젯 내부의 뷰 모서리

둥근 모서리 관련 중요 고려사항

  • 서드 파티 런처 및 기기 제조업체는 system_app_widget_background_radius 매개변수를 28dp 미만으로 재정의할 수 있습니다. system_app_widget_inner_radius 매개변수는 항상 system_app_widget_background_radius 값보다 8dp 작습니다.
  • 위젯이 @android:id/background를 사용하지 않거나 윤곽선을 기반으로 콘텐츠를 자르는 배경을 정의하지 않는 경우(android:clipToOutlinetrue로 설정), 런처는 자동으로 배경을 식별하고 최대 16dp의 둥근 모서리를 가진 직사각형을 사용하여 위젯을 자릅니다. 위젯이 Android 12와 호환되는지 확인을 참고하세요.

이전 Android 버전과의 위젯 호환성을 위해 다음 샘플 XML 파일과 같이 맞춤 속성을 정의하고 맞춤 테마를 사용하여 Android 12용으로 재정의하는 것이 좋습니다.

/values/attrs.xml

<resources>
  <attr name="backgroundRadius" format="dimension" />
</resources>

/values/styles.xml

<resources>
  <style name="MyWidgetTheme">
    <item name="backgroundRadius">@dimen/my_background_radius_dimen</item>
  </style>
</resources>

/values-31/styles.xml

<resources>
  <style name="MyWidgetTheme" parent="@android:style/Theme.DeviceDefault.DayNight">
    <item name="backgroundRadius">@android:dimen/system_app_widget_background_radius</item>
  </style>
</resources>

/drawable/my_widget_background.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android"
  android:shape="rectangle">
  <corners android:radius="?attr/backgroundRadius" />
  ...
</shape>

/layout/my_widget_layout.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  ...
  android:background="@drawable/my_widget_background" />