Skip to content

Commit e7b6b0a

Browse files
committed
Optimize and simplify Full Bleed Snap Scrolling Gallery app widget
- Flatten composition tree by removing redundant key(LocalSize.current) wrappers.\n- Hoist LocalSize and LocalContext lookups to FullBleedImageLayout to optimize recompositions.\n- Enable stable list item keying with Glance LazyColumn itemId optimization.\n- Refactor FakeImageGridDataRepository to use non-blocking coroutineScope instead of runBlocking.\n- Sanitize drawables and preview layout bindings, deleting duplicative png assets.
1 parent dcad890 commit e7b6b0a

5 files changed

Lines changed: 26 additions & 37 deletions

File tree

samples/user-interface/appwidgets/src/main/java/com/example/platform/ui/appwidgets/glance/layout/CanonicalLayoutActivity.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ private val canonicalLayoutWidgets = listOf(
304304
CanonicalLayoutRowData(
305305
rowTitle = R.string.cl_title_full_bleed_image,
306306
rowDescription = R.string.cl_description_full_bleed_image,
307-
imageRes = R.drawable.cl_activity_row_full_bleed_image,
307+
imageRes = R.drawable.sample_full_bleed_image_preview,
308308
receiver = FullBleedImageAppWidgetReceiver::class.java,
309309
),
310310
CanonicalLayoutRowData(

samples/user-interface/appwidgets/src/main/java/com/example/platform/ui/appwidgets/glance/layout/collections/data/FakeImageGridDataRepository.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ import com.example.platform.ui.appwidgets.glance.layout.collections.layout.Image
1616
import com.example.platform.ui.appwidgets.glance.layout.utils.ImageUtils.getMaxPossibleImageSize
1717
import com.example.platform.ui.appwidgets.glance.layout.utils.ImageUtils.getMaxWidgetMemoryAllowedSizeInBytes
1818
import kotlinx.coroutines.Dispatchers
19+
import kotlinx.coroutines.coroutineScope
1920
import kotlinx.coroutines.async
2021
import kotlinx.coroutines.awaitAll
2122
import kotlinx.coroutines.flow.Flow
2223
import kotlinx.coroutines.flow.MutableStateFlow
23-
import kotlinx.coroutines.runBlocking
2424
import com.example.platform.ui.appwidgets.glance.layout.computeIfAbsent as computeIfAbsentExt
2525
/**
2626
* A fake in-memory implementation of repository that produces a list of
@@ -74,7 +74,7 @@ class FakeImageGridDataRepository {
7474
val width = IMAGE_SIZE.coerceAtMost(imageSizeLimit.width)
7575
val height = width * 9 / 16
7676

77-
val mappedItems = runBlocking {
77+
val mappedItems = coroutineScope {
7878
items.map { item ->
7979
async(Dispatchers.IO) {
8080
var bitmap: Bitmap? = null

samples/user-interface/appwidgets/src/main/java/com/example/platform/ui/appwidgets/glance/layout/text/FullBleedImageAppWidget.kt

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import android.content.Context
2121
import androidx.compose.runtime.Composable
2222
import androidx.compose.runtime.collectAsState
2323
import androidx.compose.runtime.getValue
24-
import androidx.compose.runtime.key
2524
import androidx.glance.GlanceId
2625
import androidx.glance.GlanceTheme
2726
import androidx.glance.LocalSize
@@ -55,40 +54,31 @@ class FullBleedImageAppWidget : GlanceAppWidget() {
5554
override suspend fun provideGlance(context: Context, id: GlanceId) {
5655
val repo = getImageGridDataRepo(id)
5756

58-
val initialData = withContext(Dispatchers.Default) {
57+
val initialData = withContext(Dispatchers.IO) {
5958
repo.load(context)
6059
}
6160

6261
provideContent {
6362
val data by repo.data().collectAsState(initial = initialData)
6463

6564
GlanceTheme {
66-
key(LocalSize.current) {
67-
WidgetContent(
68-
data = data
69-
)
70-
}
65+
FullBleedImageLayout(
66+
data = data
67+
)
7168
}
7269
}
7370
}
7471

75-
@Composable
76-
fun WidgetContent(data: List<ImageGridItemData>?) {
77-
FullBleedImageLayout(
78-
data = data
79-
)
80-
}
81-
8272
override suspend fun providePreview(context: Context, widgetCategory: Int) {
8373
val repo = getImageGridDataRepo(AppWidgetId(0))
8474

85-
val initialData = withContext(Dispatchers.Default) {
75+
val initialData = withContext(Dispatchers.IO) {
8676
repo.load(context)
8777
}
8878

8979
provideContent {
9080
GlanceTheme {
91-
WidgetContent(
81+
FullBleedImageLayout(
9282
data = initialData.take(1)
9383
)
9484
}

samples/user-interface/appwidgets/src/main/java/com/example/platform/ui/appwidgets/glance/layout/text/layout/FullBleedImageLayout.kt

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ fun FullBleedImageLayout(
6666
data: List<ImageGridItemData>? = null,
6767
) {
6868
val size = LocalSize.current
69+
val isSmall = size.height <= 110.dp
70+
val appName = LocalContext.current.getString(R.string.sample_full_bleed_image_app_widget_name)
71+
6972
Box(
7073
modifier = GlanceModifier
7174
.fillMaxSize()
@@ -85,6 +88,8 @@ fun FullBleedImageLayout(
8588
// with fillMaxSize to bypass any LazyColumn height/scroll container measurement issues.
8689
GalleryItemCard(
8790
item = data[0],
91+
isSmall = isSmall,
92+
appName = appName,
8893
modifier = GlanceModifier.fillMaxSize()
8994
)
9095
} else {
@@ -94,9 +99,11 @@ fun FullBleedImageLayout(
9499
modifier = GlanceModifier.fillMaxSize(),
95100
verticalScrollMode = VerticalScrollMode.SnapScroll
96101
) {
97-
items(limitedData) { item ->
102+
items(limitedData, itemId = { it.key.hashCode().toLong() }) { item ->
98103
GalleryItemCard(
99104
item = item,
105+
isSmall = isSmall,
106+
appName = appName,
100107
modifier = GlanceModifier.width(size.width).height(size.height)
101108
)
102109
}
@@ -108,21 +115,18 @@ fun FullBleedImageLayout(
108115
@Composable
109116
private fun GalleryItemCard(
110117
item: ImageGridItemData,
118+
isSmall: Boolean,
119+
appName: String,
111120
modifier: GlanceModifier = GlanceModifier,
112121
) {
113-
val size = LocalSize.current
114122
val itemTitle = item.title ?: ""
115123

116124
Box(
117125
modifier = modifier,
118126
contentAlignment = Alignment.BottomStart
119127
) {
120128
// Layer 1: Full bleed background photo
121-
val imageProvider = if (item.image != null) {
122-
ImageProvider(item.image)
123-
} else {
124-
ImageProvider(R.drawable.sample_placeholder_image)
125-
}
129+
val imageProvider = item.image?.let { ImageProvider(it) } ?: ImageProvider(R.drawable.sample_placeholder_image)
126130

127131
Image(
128132
provider = imageProvider,
@@ -131,11 +135,6 @@ private fun GalleryItemCard(
131135
modifier = GlanceModifier.fillMaxSize()
132136
)
133137

134-
val appIconSize = 24.dp
135-
val spacerHeight = 4.dp
136-
137-
// Use discrete font sizing with a threshold of 110.dp (representing extremely small/XSmall layout sizes) to avoid scaling on resize.
138-
val isSmall = size.height <= 110.dp
139138
val titleFontSize = if (isSmall) {
140139
WidgetTextDimensions.primaryTextFontSizeAndMaxLines(itemTitle).first
141140
} else {
@@ -161,20 +160,19 @@ private fun GalleryItemCard(
161160
Column(
162161
modifier = GlanceModifier
163162
.fillMaxWidth()
164-
.wrapContentHeight()
165163
.padding(WidgetTextDimensions.widgetPadding),
166164
verticalAlignment = Alignment.Bottom,
167165
) {
168166
// App Logo Icon styled as a fixed size monochrome asset above the Title
169167
Image(
170168
provider = ImageProvider(R.drawable.sample_app_logo),
171-
contentDescription = null,
169+
contentDescription = appName,
172170
contentScale = ContentScale.Fit,
173-
modifier = GlanceModifier.width(appIconSize).height(appIconSize)
171+
modifier = GlanceModifier.width(AppIconSize).height(AppIconSize)
174172
)
175173

176174
if (itemTitle.isNotEmpty()) {
177-
Spacer(modifier = GlanceModifier.height(spacerHeight))
175+
Spacer(modifier = GlanceModifier.height(SpacerHeight))
178176
Text(
179177
text = itemTitle,
180178
style = TextStyle(
@@ -189,6 +187,9 @@ private fun GalleryItemCard(
189187
}
190188
}
191189

190+
private val AppIconSize = 24.dp
191+
private val SpacerHeight = 4.dp
192+
192193

193194

194195
@RequiresApi(Build.VERSION_CODES_FULL.BAKLAVA_1)
@@ -200,14 +201,12 @@ private fun FullBleedImageLayoutPreview() {
200201
ImageGridItemData(
201202
key = "0",
202203
title = "Yosemite Valley under clear blue skies",
203-
supportingText = "Yosemite National Park, California",
204204
image = null,
205205
imageContentDescription = null
206206
),
207207
ImageGridItemData(
208208
key = "1",
209209
title = "Mystical forest lake reflection at sunrise",
210-
supportingText = "Avenue of the Giants, Oregon",
211210
image = null,
212211
imageContentDescription = null
213212
)
Binary file not shown.

0 commit comments

Comments
 (0)