Posted by Michael Stillwell Developer Relations Engineer
This submit is a part of Put on OS Highlight Week. At present, we’re specializing in creating participating Put on OS tiles with new assets and up to date design steering.
Put on OS is all about offering customers with the precise info on the proper time. Whereas a full app is nice for immersive experiences, typically customers simply want a fast look at info or a easy strategy to take motion.
Tiles are quick, predictable surfaces that customers can entry with a easy swipe from their watch face. They’re designed for fast, frequent duties like checking the climate, beginning a timer, or monitoring health targets.
To streamline your workflow from idea to launch, we’re happy to announce a group of assets that will help you construct stunning and efficient tiles utilizing the Materials 3 Expressive design system.
These layouts are an evolution of a earlier model primarily based on Materials 2.5, now up to date to Materials 3 Expressive to create a contemporary, premium really feel that makes your tile a extra cohesive a part of the Put on OS.

We hope these assets function inspiration and a sensible place to begin, whether or not you are new to Put on OS growth or wanting so as to add a tile to your present app.
Get began with pattern layouts
Tiles are constructed declaratively utilizing the ProtoLayout library. Materials 3 Expressive’s Major Structure is organized round a slot-based structure. Working from high to backside, these slots are:
- An elective titleSlot for a header.
- A compulsory mainSlot to your core content material.
- An elective bottomSlot for supplemental actions.
Your app implements a TileService, which returns a structure when requested by the system. This structure is then used to construct and render the tile. Discover ways to get began with tiles.
For example, here is the “Purpose” structure for visualizing step rely. The titleSlot accommodates the “Steps” textual content, the mainSlot holds the graphic knowledge card with a progress ring and step knowledge, and the bottomSlot options the “Monitor” edge-hugging button. (The icon that seems on the high of the tile is laid out in your app’s manifest is and drawn by the system.)

The code for this structure is structured logically round these slots:
enjoyable structure( context: Context, deviceParameters: DeviceParameters, steps: Int, objective: Int ) = materialScope( context = context, deviceConfiguration = deviceParameters ) { val stepsString = NumberFormat.getNumberInstance().format(steps) val goalString = NumberFormat.getNumberInstance().format(objective) primaryLayout( titleSlot = { textual content("Steps".layoutString) }, // Alter margins to create more room when utilizing totally rounded corners margins = PrimaryLayoutMargins.MIN_PRIMARY_LAYOUT_MARGIN, mainSlot = { graphicDataCard( onClick = clickable(), peak = increase(), colours = filledTonalCardColors(), title = { textual content(stepsString.layoutString) }, content material = { textual content("of $goalString".layoutString) }, horizontalAlignment = LayoutElementBuilders.HORIZONTAL_ALIGN_END, graphic = { constructGraphic( mainContent = { circularProgressIndicator( staticProgress = 1F * steps / objective, // On supported gadgets, animate the arc dynamicProgress = DynamicFloat.onCondition( PlatformEventSources.isLayoutVisible() ) .use(1F * knowledge.steps / knowledge.objective) .elseUse(0F) .animate( CircularProgressIndicatorDefaults .recommendedAnimationSpec ), startAngleDegrees = 200F, endAngleDegrees = 520F, ) }, iconContent = { icon(ICON_ID) }, ) }, ) }, bottomSlot = { textEdgeButton(onClick = clickable()) { textual content("Monitor".layoutString) } }, ) }
With this straightforward perform, you get a great-looking, responsive tile. The ProtoLayout Material3 library handles the heavy lifting, corresponding to setting margins to keep away from clipping on spherical screens and making certain parts adapt easily to totally different show sizes.
Create customized tile layouts
Whereas our layouts cowl many widespread use instances, you may typically want a novel structure. The Materials 3 Expressive parts present a versatile basis for constructing customized designs.
To translate designs into code, begin with probably the most visually comparable structure and modify it. The next sections clarify the way to modify an present structure slot by slot.
Customise the title and backside slots
The titleSlot is commonly a textual content() factor. To confirm that the faucet targets of the opposite components are interactive, chances are you’ll want to cover the title slot on smaller gadgets. Discover ways to develop tiles for various display sizes.
primaryLayout( titleSlot = if (isLargeScreen()) { { textual content("$tasksLeft conscious duties left".layoutString) } } else { null }, // ... )
The bottomSlot offers customers with a major motion, sometimes an EdgeButton. You need to use a textEdgeButton() for a descriptive motion. Alternatively, you should use an icon corresponding to + through the use of an iconEdgeButton.
Utilizing an icon is a two-step course of:
- Outline the iconEdgeButton in your structure, giving your icon a novel useful resource ID string:
- Present the precise drawable useful resource in onTileResourcesRequest():
primaryLayout( // ... bottomSlot = { iconEdgeButton( onClick = clickable(), modifier = LayoutModifier.contentDescription("Add occasion"), iconContent = { icon("icon_plus_id") } ) } )
override enjoyable onTileResourcesRequest( requestParams: RequestBuilders.ResourcesRequest ) = Futures.immediateFuture( ResourceBuilders.Assets.Builder() .setVersion(requestParams.model) .addIdToImageMapping( "plus_icon_id", ResourceBuilders.ImageResource.Builder() .setAndroidResourceByResId( ResourceBuilders.AndroidImageResourceByResId.Builder() .setResourceId(R.drawable.outline_add_2_24) .construct() ) .construct() ) .construct() )
See Alarm.kt for a full code pattern demonstrating this method.
Customise the principle slot
The mainSlot is the place the core content material of your tile lives and the place probably the most important customization happens. Let’s stroll by way of a number of examples.
Case research: Exercise tile


This tile must adapt its structure for various display sizes. For the smaller structure, three easy iconButton parts are an ideal match. Within the bigger structure, the central button shows extra knowledge (period, unit, and an icon). Regardless that it is semantically nonetheless a button, on this case the iconDataCard factor is a greater match. It is particularly designed to show a number of items of knowledge, and we are able to simply regulate its width and peak.
iconDataCard( title = { textual content("30".layoutString, typography = DISPLAY_MEDIUM) }, content material = { textual content("Minutes".layoutString, typography = TITLE_MEDIUM) }, secondaryIcon = { icon("icon_run_id") }, form = shapes.massive, // regulate the nook form onClick = clickable(), // make factor extra distinguished on bigger screens width = if (isLargeScreen()) weight(1.5f) else increase(), peak = increase(), // ... )
See Exercise.kt for the total supply code.
Case research: Snowboarding stats tile

The design for this tile is constructed round a pill-shaped factor that shows three strains of textual content, every with distinctive typography. A textDataCard() is ideal for this, providing slots for a “title” (the metric), “content material” (the worth), and “secondaryText” (the items). These slots include default styling that you may override to match your design exactly.
enjoyable MaterialScope.statTextButton(stat: Stat) = textDataCard( onClick = clickable(), width = increase(), peak = increase(), form = shapes.extraLarge, title = { textual content( stat.worth.layoutString, typography = if (isLargeScreen()) { Typography.NUMERAL_SMALL } else { Typography.NUMERAL_EXTRA_SMALL } ) }, content material = { textual content( stat.unit.layoutString, typography = if (isLargeScreen()) { Typography.TITLE_MEDIUM } else { Typography.TITLE_SMALL } ) }, secondaryText = { textual content( stat.label.layoutString, typography = if (isLargeScreen()) { Typography.TITLE_MEDIUM } else { Typography.TITLE_SMALL } ) } )
Discover how the typography constants are assorted in accordance with the display measurement (TITLE_MEDIUM vs. TITLE_SMALL, for instance). Given the number of display and font sizes on Put on OS, it is a key method to maintain textual content legible. As a substitute of making an attempt to manually tweak your structure for each potential mixture, give attention to adjusting the typography through the use of totally different font measurement constants.
For a constant look, attempt to persist with the identical “class” of typography fixed, corresponding to BODY_MEDIUM on small screens and BODY_LARGE on bigger ones. Keep away from leaping between totally different classes, like from LABEL_LARGE to DISPLAY_SMALL, as these constants can differ in additional than simply measurement, affecting font weight and different visible properties.
See Ski.kt for the total supply code.
One other method to adapting a structure to totally different display sizes is just so as to add or take away components relying on the show measurement, as demonstrated by the Climate.kt structure. Whereas each variations show the identical present circumstances, the bigger model provides extra info to the forecast.


Customise colours
You may discover that the templates do not specify a shade scheme, but they adapt to the person’s chosen theme on Put on OS 6. This is because of dynamic theming, a system characteristic that mechanically generates a shade scheme by extracting seed colours from sources just like the person’s watch face. For tiles, that is the default conduct.

As a developer, this offers you two principal choices to your tile’s look:
Choice 1 (beneficial): Comply with dynamic shade theming. A dynamic theme is utilized by default. On this case, it’s best to present a defaultColorScheme for use as a fallback if the person disables dynamic theming or if the system does not help it. This method creates a constant and cohesive really feel, permitting your tile to combine seamlessly with the system.
val myColorScheme = ColorScheme( major = ... onPrimary = ... // 27 extra ) materialScope( defaultColorScheme = myColorScheme ) { // If the person selects "no theme" in settings, myColorScheme is used. // In any other case, the system-provided theme is used. }
Choice 2: Use your model colours. To make sure model consistency, you may pressure your tile to at all times use your customized shade scheme by setting allowDynamicTheme to false. On this case, the identical colours will at all times be used, no matter the person’s chosen shade theme.
materialScope( allowDynamicTheme = false, defaultColorScheme = myColorScheme ) { // myColorScheme is *at all times* used. }
See Theming for extra info on the theming system.
Develop and debug
To hurry up your growth cycle, Put on OS offers a number of instruments that will help you debug and take a look at your tiles immediately in Android Studio and on the command line.
Dive in and begin constructing
These assets are designed to make constructing high-quality Put on OS tiles simpler and extra inspiring. We will not wait to see what you create with them.
Discover the layouts and get began in the present day by trying out the Figma design equipment or the code on GitHub.