Migrate from tiles to widgets

Although both tiles and widgets display your content on a remote system surface, building them requires distinct approaches. Migrating your existing tile to a widget means transitioning from rigid layout generation to a dynamic, declarative UI, unlocking new capabilities and a simplified development model.

Choose your implementation strategy

If you're migrating an app that maintains a legacy tile, you must decide how your app provides content to the system. While brand-new widgets should use a single Widget Service, apps with existing tiles must choose between maintaining both services or consolidating on a single Widget Service.

Recommended: Dual service (tile + widget)

Maintaining both a tile and a widget is the recommended path for all apps that have an existing tile. Providing two distinct services provides the best possible user experience across different devices.

System Behavior for Dual-Service Setup:

OS / Device Capability Resulting Experience
Wear OS 3 Tile is used
Wear OS 4, 5, 6 Tile is used
Wear OS 7 (No partial-height support, e.g., Pixel Watch) Tile is used
Wear OS 7 (Partial-height support, e.g., Galaxy Watch) Widget is used

Alternative: Single service (widget only)

A single service handles both protocols. While this approach is faster to implement, it relies on a compatibility mode to "adapt" your widget into a tile on devices running lower versions of Wear OS.

If you choose this approach:

  1. Specify both intent filters: Your service must include intent filters for both androidx.wear.tiles.action.BIND_TILE_PROVIDER and androidx.glance.wear.action.BIND_WIDGET_PROVIDER. This ensures your widget is displayed on tile surfaces in Wear 4, 5, 6, and 7 (where required).
  2. Maintain your existing service name (for seamless upgrades): If you are replacing an active tile, keeping the same service class name ensures that users who have your tile in their carousel will see it automatically update to the new widget. While Wear OS 7 uses the group attribute in the widget configuration XML to logically link different components, versions of Wear OS lower than 7 rely on the service name to identify them as the "same" component. If you prefer to use a new service name, your app will still function perfectly; however, users on devices running Wear OS version 6 or lower will need to manually re-add the widget to their carousel.

System Behavior for Single Service Setup:

OS / Device Capability Resulting Experience
Wear OS 3 Not supported
Wear OS 4, 5, 6 Widget is displayed as a full screen tile
Wear OS 7 (No partial-height support) Widget is translated to a tile
Wear OS 7 (Partial-height support) Widget is used

*Requires renderer 1.6+.

UI Translation Tips

When translating your UI from ProtoLayout (Tiles) to Remote Compose (Widgets), the mental model shifts from imperative layout builders to a state-driven, Compose-based architecture where UI updates are handled through recomposition. Keep the following principles in mind:

  • Adopt Declarative UI: Replace imperative ProtoLayout builders (LayoutElementBuilders) with declarative Remote Compose equivalents, such as RemoteText, RemoteColumn, and RemoteBox.
  • Focus on the Core Content (mainSlot): Partial-height widgets (e.g., SMALL and LARGE container types) provide a focused, glanceable surface. Rather than porting a dense, full-screen Tile layout one-to-one, streamline your design to emphasize primary information within the main content area.
  • Redesign Edge-Aligned Actions: In the tiles architecture, screen-hugging components like the EdgeButton were anchored to a dedicated bottomSlot. Because partial-height widgets integrate directly into a vertically scrolling surface, this fixed bottomSlot paradigm no longer exists. Because edge-aligned buttons often served as highly prominent primary actions, migrating requires a deliberate UI redesign rather than a direct component swap. Evaluate alternative UX strategies for your primary actions:
    • Inline Actions: Integrate an inline RemoteButton directly within your mainSlot layout.
    • Container Taps: Consolidate the interaction by making the entire widget container tappable using a PendingIntentAction.
    • Content Pivot: Re-evaluate the widget's focus. Without a dedicated action slot, consider surfacing richer glanceable data and relying on a single tap to open the full application rather than isolating specific actions on the widget surface.
  • Migrate Event Handling (Actions vs. Lambdas): Tiles rely on interactions (like LoadAction) triggering full service callbacks to refresh the UI. Wear Widgets are client-side driven. Standard Compose lambdas cannot be run remotely; instead, provide serializable Declarative Actions (like ValueChange or PendingIntentAction). Combine these with declarative state (e.g., rememberMutableRemoteInt) to support instant UI updates without app round-trips.
  • Adapt Dimensions and Types: When migrating layout dimensions, prefer deferred layout resolution using RemoteDp (e.g., 10.rdp) over the standard Dp. This ensures the system renderer correctly calculates pixel values at display time. Similarly, use Remote Compose extension functions (.rc for Color, .rs for String, .rdp for Dp) to seamlessly convert standard Kotlin and Remote Compose types.
  • Review Sample Code: To see comprehensive examples of how to build layouts, apply semantic typography, and manage state in Remote Compose, explore the official sample code available in the Wear OS Samples repository.