Skip to content

Commit cbf500d

Browse files
authored
Merge pull request #180 from shamalip/main
Include Glance android studio preview code samples to the layouts
2 parents c494684 + 3063fb4 commit cbf500d

File tree

9 files changed

+456
-0
lines changed

9 files changed

+456
-0
lines changed

gradle/libs.versions.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,8 @@ play-services-location = { module = "com.google.android.gms:play-services-locati
126126
androidx-work-runtime-ktx = "androidx.work:work-runtime-ktx:2.9.0"
127127
androidx-core-remoteviews = "androidx.core:core-remoteviews:1.0.0"
128128
androidx-glance-appwidget = {group = "androidx.glance", name = "glance-appwidget", version.ref = "glance"}
129+
androidx-glance-preview = {group = "androidx.glance", name = "glance-preview", version.ref = "glance"}
130+
androidx-glance-appwidget-preview = {group = "androidx.glance", name = "glance-appwidget-preview", version.ref = "glance"}
129131
androidx-glance-material3 = {group = "androidx.glance", name = "glance-material3", version.ref = "glance"}
130132
androidx-graphics-core = { group = "androidx.graphics", name = "graphics-core", version = "1.0.0-beta01" }
131133
androidx-startup = 'androidx.startup:startup-runtime:1.1.1'

samples/user-interface/appwidgets/build.gradle.kts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,7 @@ dependencies {
3636
// Recommended to use WorkManager to load data for widgets
3737
implementation(libs.androidx.work.runtime.ktx)
3838
implementation(libs.material)
39+
40+
debugImplementation(libs.androidx.glance.preview)
41+
debugImplementation(libs.androidx.glance.appwidget.preview)
3942
}

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

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import androidx.glance.GlanceModifier
1111
import androidx.glance.GlanceTheme
1212
import androidx.glance.Image
1313
import androidx.glance.ImageProvider
14+
import androidx.glance.LocalContext
1415
import androidx.glance.LocalSize
1516
import androidx.glance.action.Action
1617
import androidx.glance.action.clickable
@@ -24,11 +25,15 @@ import androidx.glance.layout.Box
2425
import androidx.glance.layout.fillMaxSize
2526
import androidx.glance.layout.padding
2627
import androidx.glance.layout.size
28+
import androidx.glance.preview.ExperimentalGlancePreviewApi
29+
import androidx.glance.preview.Preview
2730
import androidx.glance.semantics.contentDescription
2831
import androidx.glance.semantics.semantics
2932
import androidx.glance.text.FontWeight
3033
import androidx.glance.text.Text
3134
import androidx.glance.text.TextStyle
35+
import com.example.platform.ui.appwidgets.R
36+
import com.example.platform.ui.appwidgets.glance.layout.collections.data.FakeActionListDataRepository.Companion.demoData
3237
import com.example.platform.ui.appwidgets.glance.layout.collections.layout.ActionListLayoutDimensions.circularCornerRadius
3338
import com.example.platform.ui.appwidgets.glance.layout.collections.layout.ActionListLayoutDimensions.filledItemCornerRadius
3439
import com.example.platform.ui.appwidgets.glance.layout.collections.layout.ActionListLayoutDimensions.filledItemPadding
@@ -42,6 +47,9 @@ import com.example.platform.ui.appwidgets.glance.layout.collections.layout.Actio
4247
import com.example.platform.ui.appwidgets.glance.layout.collections.layout.ActionListLayoutSize.Large
4348
import com.example.platform.ui.appwidgets.glance.layout.collections.layout.ActionListLayoutSize.Small
4449
import com.example.platform.ui.appwidgets.glance.layout.utils.ActionUtils.actionStartDemoActivity
50+
import com.example.platform.ui.appwidgets.glance.layout.utils.LargeWidgetPreview
51+
import com.example.platform.ui.appwidgets.glance.layout.utils.MediumWidgetPreview
52+
import com.example.platform.ui.appwidgets.glance.layout.utils.SmallWidgetPreview
4553

4654
/**
4755
* A layout focused on presenting list of two-state actions represented by a title (1-2 words),
@@ -510,3 +518,43 @@ private object ActionListLayoutDimensions {
510518
/** Corner radius to achieve circular shape. */
511519
val circularCornerRadius = 200.dp
512520
}
521+
522+
/**
523+
* Preview sizes for the widget covering the breakpoints.
524+
*
525+
* This allows verifying updates across multiple breakpoints.
526+
*/
527+
@OptIn(ExperimentalGlancePreviewApi::class)
528+
@Preview(widthDp = 259, heightDp = 200)
529+
@Preview(widthDp = 438, heightDp = 200)
530+
@Preview(widthDp = 644, heightDp = 200)
531+
private annotation class ActionListBreakpointPreviews
532+
533+
/**
534+
* Previews for the action list layout.
535+
*
536+
* First we look at the previews at defined breakpoints, tweaking them as necessary. In addition,
537+
* the previews at standard sizes allows us to quickly verify updates across min / max and common
538+
* widget sizes without needing to run the app or manually place the widget.
539+
*/
540+
@ActionListBreakpointPreviews
541+
@SmallWidgetPreview
542+
@MediumWidgetPreview
543+
@LargeWidgetPreview
544+
@Composable
545+
private fun ActionListLayoutPreview() {
546+
val context = LocalContext.current
547+
548+
ActionListLayout(
549+
title = context.getString(R.string.sample_action_list_app_widget_name),
550+
titleIconRes = R.drawable.sample_home_icon,
551+
titleBarActionIconRes = R.drawable.sample_power_settings_icon,
552+
titleBarActionIconContentDescription = context.getString(
553+
R.string.sample_action_list_settings_label
554+
),
555+
titleBarAction = actionStartDemoActivity("Power settings title bar action"),
556+
items = demoData,
557+
checkedItems = listOf("1", "3"),
558+
actionButtonClick = {},
559+
)
560+
}

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

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import androidx.compose.ui.unit.sp
88
import androidx.glance.GlanceModifier
99
import androidx.glance.GlanceTheme
1010
import androidx.glance.ImageProvider
11+
import androidx.glance.LocalContext
1112
import androidx.glance.LocalSize
1213
import androidx.glance.action.Action
1314
import androidx.glance.appwidget.components.CircleIconButton
@@ -16,10 +17,13 @@ import androidx.glance.appwidget.components.TitleBar
1617
import androidx.glance.layout.fillMaxSize
1718
import androidx.glance.layout.fillMaxWidth
1819
import androidx.glance.layout.padding
20+
import androidx.glance.preview.ExperimentalGlancePreviewApi
21+
import androidx.glance.preview.Preview
1922
import androidx.glance.text.FontWeight
2023
import androidx.glance.text.Text
2124
import androidx.glance.text.TextStyle
2225
import com.example.platform.ui.appwidgets.R
26+
import com.example.platform.ui.appwidgets.glance.layout.collections.data.FakeCheckListDataRepository.Companion.demoData
2327
import com.example.platform.ui.appwidgets.glance.layout.collections.layout.CheckListLayoutDimensions.checkListRowStartPadding
2428
import com.example.platform.ui.appwidgets.glance.layout.collections.layout.CheckListLayoutDimensions.checkListRowEndPadding
2529
import com.example.platform.ui.appwidgets.glance.layout.collections.layout.CheckListLayoutDimensions.scaffoldHorizontalPadding
@@ -29,6 +33,9 @@ import com.example.platform.ui.appwidgets.glance.layout.collections.layout.Check
2933
import com.example.platform.ui.appwidgets.glance.layout.collections.layout.CheckListLayoutSize.Companion.showTitleBar
3034
import com.example.platform.ui.appwidgets.glance.layout.collections.layout.CheckListLayoutSize.Small
3135
import com.example.platform.ui.appwidgets.glance.layout.utils.ActionUtils.actionStartDemoActivity
36+
import com.example.platform.ui.appwidgets.glance.layout.utils.LargeWidgetPreview
37+
import com.example.platform.ui.appwidgets.glance.layout.utils.MediumWidgetPreview
38+
import com.example.platform.ui.appwidgets.glance.layout.utils.SmallWidgetPreview
3239

3340
/**
3441
* A layout focused on presenting list of items in a check list. Content is displayed in a
@@ -410,4 +417,46 @@ private object CheckListLayoutDimensions {
410417
val checkListRowStartPadding = 2.dp
411418
// Padding to be applied on right of each item if there isn't a icon button on right.
412419
val checkListRowEndPadding = widgetPadding
420+
}
421+
422+
/**
423+
* Preview sizes of layout at the configured width breakpoints.
424+
*/
425+
@OptIn(ExperimentalGlancePreviewApi::class)
426+
@Preview(widthDp = 259, heightDp = 200)
427+
@Preview(widthDp = 303, heightDp = 200)
428+
@Preview(widthDp = 350, heightDp = 200)
429+
private annotation class CheckListBreakpointPreviews
430+
431+
/**
432+
* Previews for the check list layout.
433+
*
434+
* First we look at the previews at defined breakpoints, tweaking them as necessary. In addition,
435+
* the previews at standard sizes allows us to quickly verify updates across min / max and common
436+
* widget sizes without needing to run the app or manually place the widget.
437+
*/
438+
@CheckListBreakpointPreviews
439+
@SmallWidgetPreview
440+
@MediumWidgetPreview
441+
@LargeWidgetPreview
442+
@Composable
443+
private fun CheckListLayoutPreview() {
444+
val context = LocalContext.current
445+
CheckListLayout(
446+
title = context.getString(R.string.sample_check_list_app_widget_name),
447+
titleIconRes = R.drawable.sample_pin_icon,
448+
titleBarActionIconRes = R.drawable.sample_add_icon,
449+
titleBarActionIconContentDescription = context.getString(
450+
R.string.sample_add_button_text,
451+
),
452+
titleBarAction = actionStartDemoActivity("Add icon in title bar"),
453+
items = demoData,
454+
checkedItems = listOf("1"),
455+
checkButtonContentDescription = context.getString(
456+
R.string.sample_mark_done_button_content_description,
457+
),
458+
checkedIconRes = R.drawable.sample_checked_circle_icon,
459+
unCheckedIconRes = R.drawable.sample_circle_icon,
460+
onCheck = {},
461+
)
413462
}

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

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import androidx.glance.GlanceModifier
1010
import androidx.glance.GlanceTheme
1111
import androidx.glance.Image
1212
import androidx.glance.ImageProvider
13+
import androidx.glance.LocalContext
1314
import androidx.glance.LocalSize
1415
import androidx.glance.action.clickable
1516
import androidx.glance.appwidget.components.CircleIconButton
@@ -22,6 +23,8 @@ import androidx.glance.layout.fillMaxSize
2223
import androidx.glance.layout.fillMaxWidth
2324
import androidx.glance.layout.padding
2425
import androidx.glance.layout.wrapContentHeight
26+
import androidx.glance.preview.ExperimentalGlancePreviewApi
27+
import androidx.glance.preview.Preview
2528
import androidx.glance.text.FontWeight
2629
import androidx.glance.text.Text
2730
import androidx.glance.text.TextStyle
@@ -36,6 +39,9 @@ import com.example.platform.ui.appwidgets.glance.layout.collections.layout.Image
3639
import com.example.platform.ui.appwidgets.glance.layout.collections.layout.ImageGridLayoutSize.Medium
3740
import com.example.platform.ui.appwidgets.glance.layout.collections.layout.ImageGridLayoutSize.Small
3841
import com.example.platform.ui.appwidgets.glance.layout.utils.ActionUtils
42+
import com.example.platform.ui.appwidgets.glance.layout.utils.LargeWidgetPreview
43+
import com.example.platform.ui.appwidgets.glance.layout.utils.MediumWidgetPreview
44+
import com.example.platform.ui.appwidgets.glance.layout.utils.SmallWidgetPreview
3945

4046
/**
4147
* A layout focused on presenting a grid of images (with optional title and supporting text). The
@@ -295,4 +301,105 @@ private object ImageGridLayoutDimensions {
295301
else -> 1
296302
}
297303
}
304+
}
305+
306+
/**
307+
* Preview sizes for the widget covering the width based breakpoints of the image grid layout.
308+
*
309+
* This allows verifying updates across multiple breakpoints.
310+
*/
311+
@OptIn(ExperimentalGlancePreviewApi::class)
312+
@Preview(widthDp = 319, heightDp = 200)
313+
@Preview(widthDp = 321, heightDp = 200)
314+
@Preview(widthDp = 518, heightDp = 200)
315+
@Preview(widthDp = 520, heightDp = 200)
316+
private annotation class ImageGridBreakpointPreviews
317+
318+
/**
319+
* Previews for the image grid layout with both title and supporting text below the image
320+
*
321+
* First we look at the previews at defined breakpoints, tweaking them as necessary. In addition,
322+
* the previews at standard sizes allows us to quickly verify updates across min / max and common
323+
* widget sizes without needing to run the app or manually place the widget.
324+
*/
325+
@ImageGridBreakpointPreviews
326+
@SmallWidgetPreview
327+
@MediumWidgetPreview
328+
@LargeWidgetPreview
329+
@Composable
330+
private fun ImageTextGridLayoutPreview() {
331+
val context = LocalContext.current
332+
333+
ImageGridLayout(
334+
title = context.getString(R.string.sample_image_grid_app_widget_name),
335+
titleIconRes = R.drawable.sample_grid_icon,
336+
titleBarActionIconRes = R.drawable.sample_refresh_icon,
337+
titleBarActionIconContentDescription = context.getString(
338+
R.string.sample_refresh_icon_button_label
339+
),
340+
titleBarAction = {},
341+
items = listOf(
342+
ImageGridItemData(
343+
key = "0",
344+
image = null, // placeholder
345+
imageContentDescription = "A single water droplet rests in a budding red pansy.",
346+
title = "A single water droplet rests in a budding red pansy.",
347+
supportingText = "193 views"
348+
),
349+
ImageGridItemData(
350+
key = "1",
351+
image = null, // placeholder
352+
imageContentDescription = "A single water droplet rests in a budding red pansy.",
353+
title = "A single water droplet rests in a budding red pansy.",
354+
supportingText = "193 views"
355+
),
356+
ImageGridItemData(
357+
key = "2",
358+
image = null, // placeholder
359+
imageContentDescription = "Green plant, sky and flowers",
360+
title = "Green plant, sky and flowers",
361+
supportingText = "99,467 views"
362+
),
363+
ImageGridItemData(
364+
key = "3",
365+
image = null, // placeholder
366+
imageContentDescription = "A snow-shoer walking up Strelapass",
367+
title = "A snow-shoer walking up Strelapass",
368+
supportingText = "3,033 views"
369+
)
370+
)
371+
)
372+
}
373+
374+
/**
375+
* Previews for the image grid layout with only images
376+
*
377+
* First we look at the previews at defined breakpoints, tweaking them as necessary. In addition,
378+
* the previews at standard sizes allows us to quickly verify updates across min / max and common
379+
* widget sizes without needing to run the app or manually place the widget.
380+
*/
381+
@ImageGridBreakpointPreviews
382+
@SmallWidgetPreview
383+
@MediumWidgetPreview
384+
@LargeWidgetPreview
385+
@Composable
386+
private fun ImageOnlyGridLayoutPreview() {
387+
val context = LocalContext.current
388+
389+
ImageGridLayout(
390+
title = context.getString(R.string.sample_image_grid_app_widget_name),
391+
titleIconRes = R.drawable.sample_grid_icon,
392+
titleBarActionIconRes = R.drawable.sample_refresh_icon,
393+
titleBarActionIconContentDescription = context.getString(
394+
R.string.sample_refresh_icon_button_label
395+
),
396+
titleBarAction = {},
397+
items = (0..5).map { index ->
398+
ImageGridItemData(
399+
key = "$index",
400+
image = null, // placeholder
401+
imageContentDescription = null,
402+
)
403+
}
404+
)
298405
}

0 commit comments

Comments
 (0)