Skip to content

Commit 3b12623

Browse files
committed
refactor FullBleedImageLayout
1 parent 99539fd commit 3b12623

1 file changed

Lines changed: 17 additions & 37 deletions

File tree

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

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

Lines changed: 17 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@ import androidx.annotation.RequiresApi
2121
import androidx.compose.runtime.Composable
2222
import androidx.compose.ui.graphics.Color
2323
import androidx.compose.ui.unit.dp
24-
import androidx.compose.ui.unit.sp
25-
import androidx.glance.unit.ColorProvider
2624
import androidx.glance.GlanceModifier
2725
import androidx.glance.Image
2826
import androidx.glance.ImageProvider
@@ -32,20 +30,21 @@ import androidx.glance.appwidget.cornerRadius
3230
import androidx.glance.appwidget.lazy.LazyColumn
3331
import androidx.glance.appwidget.lazy.VerticalScrollMode
3432
import androidx.glance.appwidget.lazy.items
33+
import androidx.glance.background
3534
import androidx.glance.layout.Alignment
3635
import androidx.glance.layout.Box
3736
import androidx.glance.layout.Column
3837
import androidx.glance.layout.ContentScale
39-
import androidx.glance.layout.Spacer
4038
import androidx.glance.layout.fillMaxSize
4139
import androidx.glance.layout.fillMaxWidth
4240
import androidx.glance.layout.height
4341
import androidx.glance.layout.padding
42+
import androidx.glance.layout.size
4443
import androidx.glance.layout.width
45-
import androidx.glance.layout.wrapContentHeight
4644
import androidx.glance.text.FontWeight
4745
import androidx.glance.text.Text
4846
import androidx.glance.text.TextStyle
47+
import androidx.glance.unit.ColorProvider
4948
import com.example.platform.ui.appwidgets.R
5049
import com.example.platform.ui.appwidgets.glance.layout.collections.layout.ImageGridItemData
5150
import com.example.platform.ui.appwidgets.glance.layout.collections.layout.NoDataContent
@@ -54,10 +53,9 @@ import com.example.platform.ui.appwidgets.glance.layout.utils.MediumWidgetPrevie
5453
import com.example.platform.ui.appwidgets.glance.layout.utils.SmallWidgetPreview
5554

5655
/**
57-
* A beautiful canonical layout featuring an edge-to-edge full bleed gallery with snapping
58-
* vertical scroll support, reusing the unified [ImageGridItemData] schema.
56+
* A full bleed snap scrolling gallery canonical layout using [ImageGridItemData].
5957
*
60-
* Each featured item displays an edge-to-edge landscape background photo with overlaid
58+
* Each item displays an edge-to-edge background photo with overlaid
6159
* title and caption details that auto-scale to fit the current widget size.
6260
*/
6361
@RequiresApi(Build.VERSION_CODES_FULL.BAKLAVA_1)
@@ -84,8 +82,9 @@ fun FullBleedImageLayout(
8482
actionButtonOnClick = actionStartDemoActivity("on-click of info button in no data view")
8583
)
8684
} else if (data.size == 1) {
87-
// If there's only 1 item (such as in the widget preview), render directly
88-
// with fillMaxSize to bypass any LazyColumn height/scroll container measurement issues.
85+
// If there's only 1 item (like in the widget preview), render with fillMaxSize to
86+
// bypass LazyColumn measurement issues where the generated widget preview item doesn't
87+
// fill the widget bounds.
8988
GalleryItemCard(
9089
item = data[0],
9190
isSmall = isSmall,
@@ -94,10 +93,9 @@ fun FullBleedImageLayout(
9493
)
9594
} else {
9695
val limitedData = data.take(5)
97-
// LazyColumn with SnapScroll mode enabled
9896
LazyColumn(
9997
modifier = GlanceModifier.fillMaxSize(),
100-
verticalScrollMode = VerticalScrollMode.SnapScroll
98+
verticalScrollMode = VerticalScrollMode.SnapScrollMatchHeight(size.height)
10199
) {
102100
items(limitedData, itemId = { it.key.hashCode().toLong() }) { item ->
103101
GalleryItemCard(
@@ -125,7 +123,6 @@ private fun GalleryItemCard(
125123
modifier = modifier,
126124
contentAlignment = Alignment.BottomStart
127125
) {
128-
// Layer 1: Full bleed background photo
129126
val imageProvider = item.image?.let { ImageProvider(it) } ?: ImageProvider(R.drawable.sample_placeholder_image)
130127

131128
Image(
@@ -141,57 +138,40 @@ private fun GalleryItemCard(
141138
WidgetTextDimensions.maxPrimaryTextFontSize
142139
}
143140

144-
// Determine a safe, explicit height for the gradient scrim area based on the size class
145-
val scrimHeight = if (isSmall) 100.dp else 140.dp
146-
147-
// Layer 2: Independent background gradient scrim positioned at the bottom of the card.
148-
// Giving this a hardcoded height guarantees it cannot stretch to full-widget height.
149-
Image(
150-
provider = ImageProvider(R.drawable.sample_scrim_gradient),
151-
contentDescription = null,
152-
contentScale = ContentScale.FillBounds,
153-
modifier = GlanceModifier
154-
.fillMaxWidth()
155-
.height(scrimHeight)
156-
)
157-
158-
// Layer 3: Independent content Column with no background, positioned at the bottom of the card.
159-
// Because it has no background and wraps content, padding is never squished.
160141
Column(
161142
modifier = GlanceModifier
162143
.fillMaxWidth()
144+
// Implementing a partial gradient scrim by applying a background modifier directly
145+
// to a text Column, shown here, results in the gradient stretching to fill the
146+
// entire widget. You can work around this by using an independent sibling Image
147+
// with a hardcoded height (100.dp) to restrict a gradient to the bottom.
148+
.background(ImageProvider(R.drawable.sample_scrim_gradient))
163149
.padding(WidgetTextDimensions.widgetPadding),
164150
verticalAlignment = Alignment.Bottom,
165151
) {
166-
// App Logo Icon styled as a fixed size monochrome asset above the Title
152+
// App Logo Icon styled as a fixed size monochrome asset above the Title as the Caption
167153
Image(
168154
provider = ImageProvider(R.drawable.sample_app_logo),
169155
contentDescription = appName,
170156
contentScale = ContentScale.Fit,
171-
modifier = GlanceModifier.width(AppIconSize).height(AppIconSize)
157+
modifier = GlanceModifier.size(24.dp)
172158
)
173159

174160
if (itemTitle.isNotEmpty()) {
175-
Spacer(modifier = GlanceModifier.height(SpacerHeight))
176161
Text(
177162
text = itemTitle,
178163
style = TextStyle(
179164
color = ColorProvider(Color.White),
180165
fontWeight = FontWeight.Bold,
181166
fontSize = titleFontSize
182167
),
183-
modifier = GlanceModifier.fillMaxWidth()
168+
modifier = GlanceModifier.fillMaxWidth().padding(top = 4.dp)
184169
)
185170
}
186171
}
187172
}
188173
}
189174

190-
private val AppIconSize = 24.dp
191-
private val SpacerHeight = 4.dp
192-
193-
194-
195175
@RequiresApi(Build.VERSION_CODES_FULL.BAKLAVA_1)
196176
@SmallWidgetPreview
197177
@MediumWidgetPreview

0 commit comments

Comments
 (0)