You can enhance your tile experience further by making it interactive. By adding
the Clickable
modifier to a layout element within the tile, you can react
to a user tapping that layout element.
This page lists several common actions that users perform within interactive tiles, along with guidance on how to implement this behavior in your app's tiles.
Load a new tile layout
Use LoadAction
to refresh the layout of your tile when the user taps an
interactive element.
In the following code snippet, the clickable ID set in setId()
is passed
along to the onTileRequest()
call, so you can render a different layout based
on this ID:
override fun onTileRequest(requestParams: TileRequest) = Futures.immediateFuture(
Tile.Builder()
.setResourcesVersion("1")
.setTileTimeline(Timeline.fromLayoutElement(
when(requestParams.currentState.lastClickableId) {
"foo" -> myFooLayout()
else -> myOtherLayout()
}
)).build()
)
Update state within the tile
If an interactive element in your tile has several possible states, use a
LoadAction
to show the element's new value. In the following code snippet, the
tile shows the updated value of a checkbox:
private fun checkboxChip(
checkboxValue: Boolean,
deviceParameters: DeviceParametersBuilders.DeviceParameters
): Chip =
Chip.Builder(
context,
Clickable.Builder()
.setOnClick(LoadAction.Builder()
.build()
).build(),
deviceParameters
).setIconContent(if (checkboxValue) "check" else "checkoff")
// Set checkbox labels and colors here.
.build()
Request a refresh of the tile's contents
To request an update to the tile's entire contents, use LoadAction
and update
the tile's request state, as shown in the following code snippet.
private fun tappableElement(): LayoutElement =
Button.Builder(this, Clickable.Builder()
.setId("foo")
.setOnClick(LoadAction.Builder()
.setRequestState(
StateBuilders.State.Builder()
/* Update state information here. */
.build()
).build()
).build())
.setTextContent("Tap me!")
.build()
Load an activity using a deep link
To load an activity using a deep link, associate a clickable element with a
LoadAction
object:
private fun tappableElement(): LayoutElement =
Text.Builder()
.setText("Tap me!")
.setModifiers(Modifiers.Builder()
.setClickable(Clickable.Builder()
.setId("foo")
.setOnClick(LoadAction.Builder().build())
.build()
).build()
).build()
Then, in your onTileRequest()
method, use a TaskStackBuilder
object as a
helper:
override fun onTileRequest(requestParams: TileRequest): ListenableFuture<TileBuilders.Tile> {
val lastClickableId = requestParams.currentState.lastClickableId
if (lastClickableId == "foo") {
TaskStackBuilder.create(this)
.addNextIntentWithParentStack(Intent(
Intent.ACTION_VIEW,
"https://www.example.com/$lastClickableId".toUri(),
context,
MyWearOsAppActivity::class.java
))
.startActivities()
}
// The user clicked somewhere else on the tile instead.
}
Load an exported activity
To load an exported activity by class name and with intent extras, use a
LaunchAction
.
private fun tappableElement(): LayoutElement =
Text.Builder(this, "Tap me!")
.setModifiers(Modifiers.Builder()
.setClickable(Clickable.Builder()
.setId("foo")
.setOnClick(ActionBuilders.launchAction(
ComponentName("my.package.name", "MyActivity")
)).build()
).build()
).build()
Inside the launched activity, you can retrieve the ID that was used for the tile as shown in the following example:
class MyActivity : FragmentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val clickableId =
intent.getStringExtra(TileService.EXTRA_CLICKABLE_ID)
// clickableId will be "foo" when launched from the Tile
}
}
Recommended for you
- Note: link text is displayed when JavaScript is off
- Create your first Tile in Wear OS
- Migrate to ProtoLayout namespaces
- Show dynamic updates in tiles