SizeMode

sealed interface SizeMode

Known direct subclasses
PreviewSizeMode

This marker interface determines which SizeModes can be used for preview compositions.

SizeMode.Exact

The GlanceAppWidget provides a UI for each size the App Widget may be displayed at.

SizeMode.Responsive

The GlanceAppWidget provides a UI for a fixed set of sizes.

SizeMode.Single

The GlanceAppWidget provides a single UI.

Known indirect subclasses
SizeMode.Responsive

The GlanceAppWidget provides a UI for a fixed set of sizes.

SizeMode.Single

The GlanceAppWidget provides a single UI.


Modes describing how the GlanceAppWidget should handle size specification.

Note: Size modes that support multiple sizes (Exact, Responsive) run the composable passed to to provideContent concurrently for each size. This has a number of important implications. Since an instance of the content is running for each size, all of the State objects in the content will have an instance for each size.

For example, in Exact mode, let's say the AppWidgetHost asks for 2 sizes, portrait and landscape. In the code below, there will end up being two instances of the count variable, one for each size:

provideContent {
var count by remember { mutableStateOf(0) }
Button(
text = "Increment count: $count",
onClick = { count++ }
)
}

If the button is clicked while the widget is displayed in portrait size, the count variable is updated for both sizes. This is so that, if the device orientation changes and the host displays the landscape layout, it will be consistent with the state in portrait. This works because lambdas that are at the same place in the composition will be mapped to the same default key in all sizes. So triggering one will trigger the corresponding lambdas in other sizes.

This means that lambdas will be called multiple times when they are triggered, which can have unexpected effects if state is not handled correctly. In order to prevent some external action from being triggered multiple times at once, you should conflate requests so that only one is active at a time, e.g. using MutableStateFlow.

To prevent this behavior, you can use the androidx.compose.runtime.key composable to set different default lambda keys for each size, so that they do not trigger each other:

provideContent {
key(LocalSize.current) {
var count by remember { mutableStateOf(0) }
Button(
text = "Increment count: $count",
onClick = { count++ }
)
}
}

To disable this behavior on a per-lambda basis, use androidx.glance.action.action to set a custom lambda key based on the current size:

provideContent {
var count by remember { mutableStateOf(0) }
Button(
text = "Increment count: $count",
onClick = action("incrementCount-${LocalSize.current}") { count++ }
)
}

In both of the last two examples, when the button is clicked, only the lambda for the currently visible size will be triggered.

Note that the above does not work for effects, which will always be triggered for each size. Use effects to update state variables in the composition, otherwise be sure to handle any duplicate triggering that may occur.

Summary

Nested types

The GlanceAppWidget provides a UI for each size the App Widget may be displayed at.

The GlanceAppWidget provides a UI for a fixed set of sizes.

The GlanceAppWidget provides a single UI.