Yazan
Yazan

Reputation: 151

How to dynamically adjust Jetpack Glance App Widget layout on resize?

I'm building an Android widget with Jetpack Glance and want to adjust the layout based on widget width changes. I’ve tried several approaches but haven’t found a consistent way to handle dynamic resizing across API levels.

Here’s what I tried so far:

SizeMode.Responsive: I used SizeMode.Responsive in GlanceAppWidget to set different layouts for small and large sizes. However, this only worked inconsistently across API levels (mostly on API 33+), making it unreliable for older versions.

onAppWidgetOptionsChanged: I also attempted to use onAppWidgetOptionsChanged() in a traditional AppWidgetProvider to detect resizing and update the Glance widget. But since the update function in GlanceAppWidget is marked internal, calling it from onAppWidgetOptionsChanged() didn’t work as expected, and I couldn’t reliably trigger layout updates based on the widget’s new width.

What I Expect: I’m looking for a solution to handle size changes reliably across all API levels, allowing me to show or hide different composables in Jetpack Glance based on width changes. Any advice or workarounds would be appreciated!

Here’s my current Glance setup:

class WidgetReceiver : GlanceAppWidgetReceiver() {
override val glanceAppWidget: GlanceAppWidget = AppWidget()
}

class AppWidget : GlanceAppWidget() {
override suspend fun provideGlance(context: Context, id: GlanceId) {
    provideContent {
        MyContent(context)
    }
}

@Composable
private fun MyContent(context: Context) {
    WidgetContent()
}
}

Any help would be greatly appreciated!

Upvotes: 1

Views: 361

Answers (1)

Yazan
Yazan

Reputation: 151

I have found a smooth solution, thanks to @JanBína, using Size.Exact

class AppWidget : GlanceAppWidget() {

override val sizeMode = SizeMode.Exact

override suspend fun provideGlance(context: Context, id: GlanceId) {
    provideContent {
        MyContent(context)
    }
}

@Composable
private fun MyContent(context: Context) {
    val size = LocalSize.current

    Log.d("WidgetContent", "Size: $size")
    
    WidgetContent()
}
}

Log while resizing the widget:

WidgetContent D Size: 160.0.dp x 176.0.dp

WidgetContent D Size: 248.0.dp x 176.0.dp

WidgetContent D Size: 336.0.dp x 176.0.dp

WidgetContent D Size: 336.0.dp x 272.0.dp

Upvotes: 1

Related Questions