Skip to content

Add example of Lottie animation #572

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Aug 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions wear/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,21 @@
android:resource="@drawable/tile_preview" />
</service>

<service
android:name=".snippets.tile.LottieAnimation"
android:label="@string/tile_label"
android:description="@string/tile_description"
android:icon="@mipmap/ic_launcher"
android:exported="true"
android:permission="com.google.android.wearable.permission.BIND_TILE_PROVIDER">
<intent-filter>
<action android:name="androidx.wear.tiles.action.BIND_TILE_PROVIDER" />
</intent-filter>

<meta-data android:name="androidx.wear.tiles.PREVIEW"
android:resource="@drawable/tile_preview" />
</service>

<activity
android:name=".snippets.alwayson.AlwaysOnActivity"
android:label="0 Stopwatch"
Expand Down
52 changes: 52 additions & 0 deletions wear/src/main/java/com/example/wear/snippets/tile/Animations.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ import androidx.wear.protolayout.ModifiersBuilders
import androidx.wear.protolayout.ModifiersBuilders.AnimatedVisibility
import androidx.wear.protolayout.ModifiersBuilders.DefaultContentTransitions
import androidx.wear.protolayout.ModifiersBuilders.Modifiers
import androidx.wear.protolayout.ResourceBuilders
import androidx.wear.protolayout.ResourceBuilders.Resources
import androidx.wear.protolayout.TimelineBuilders.Timeline
import androidx.wear.protolayout.TriggerBuilders.createOnVisibleTrigger
import androidx.wear.protolayout.TypeBuilders.FloatProp
import androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationParameters
import androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec
Expand All @@ -38,11 +41,15 @@ import androidx.wear.protolayout.material.CircularProgressIndicator
import androidx.wear.protolayout.material.Text
import androidx.wear.protolayout.material.layouts.EdgeContentLayout
import androidx.wear.tiles.RequestBuilders
import androidx.wear.tiles.RequestBuilders.ResourcesRequest
import androidx.wear.tiles.TileBuilders.Tile
import androidx.wear.tiles.TileService
import com.example.wear.R
import com.google.common.util.concurrent.Futures
import com.google.common.util.concurrent.ListenableFuture

// In a real implementation, this needs to change whenever the resources
// change, to ensure the updated resources are loaded.
private const val RESOURCES_VERSION = "1"
private const val someTileText = "Hello"
private val deviceParameters = DeviceParametersBuilders.DeviceParameters.Builder().build()
Expand Down Expand Up @@ -310,3 +317,48 @@ class AnimationGeometricTranslation : TileService() {
// [END android_wear_tile_animations_geometric_translation]
}
}

// [START android_wear_tile_animations_lottie]
class LottieAnimation : TileService() {

val lottieResourceId = "lottie_animation"

override fun onTileRequest(requestParams: RequestBuilders.TileRequest): ListenableFuture<Tile> {

val layout =
LayoutElementBuilders.Image.Builder()
.setWidth(dp(150f))
.setHeight(dp(150f))
.setResourceId(lottieResourceId)
.build()

return Futures.immediateFuture(
Tile.Builder()
.setResourcesVersion(RESOURCES_VERSION)
.setTileTimeline(Timeline.fromLayoutElement(layout))
.build()
)
}

override fun onTileResourcesRequest(
requestParams: ResourcesRequest
): ListenableFuture<Resources> {

val lottieImage =
ResourceBuilders.ImageResource.Builder()
.setAndroidLottieResourceByResId(
ResourceBuilders.AndroidLottieResourceByResId.Builder(R.raw.lottie)
.setStartTrigger(createOnVisibleTrigger())
.build()
)
.build()

return Futures.immediateFuture(
Resources.Builder()
.setVersion(requestParams.version)
.addIdToImageMapping(lottieResourceId, lottieImage)
.build()
)
}
}
// [END android_wear_tile_animations_lottie]
240 changes: 240 additions & 0 deletions wear/src/main/res/raw/lottie.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
{
"v": "5.12.2",
"fr": 29.9700012207031,
"ip": 0,
"op": 149.000006068894,
"w": 256,
"h": 256,
"nm": "TestLotties",
"ddd": 0,
"assets": [],
"layers": [
{
"ddd": 0,
"ind": 1,
"ty": 4,
"nm": "Shape Layer 1",
"sr": 1,
"ks": {
"o": {
"a": 0,
"k": 100,
"ix": 11
},
"r": {
"a": 0,
"k": 0,
"ix": 10
},
"p": {
"a": 0,
"k": [128, 128, 0],
"ix": 2,
"l": 2
},
"a": {
"a": 0,
"k": [0, 0, 0],
"ix": 1,
"l": 2
},
"s": {
"a": 0,
"k": [100, 100, 100],
"ix": 6,
"l": 2
}
},
"ao": 0,
"shapes": [
{
"ty": "gr",
"it": [
{
"ty": "rc",
"d": 1,
"s": {
"a": 0,
"k": [147.598, 101.668],
"ix": 2
},
"p": {
"a": 0,
"k": [0, 0],
"ix": 3
},
"r": {
"a": 0,
"k": 0,
"ix": 4
},
"nm": "Rectangle Path 1",
"mn": "ADBE Vector Shape - Rect",
"hd": false
},
{
"ty": "fl",
"c": {
"a": 0,
"k": [0.373262771906, 0.896561446844, 0.9078125, 1],
"ix": 4
},
"o": {
"a": 0,
"k": 100,
"ix": 5
},
"r": 1,
"bm": 0,
"nm": "Fill 1",
"mn": "ADBE Vector Graphic - Fill",
"hd": false
},
{
"ty": "tr",
"p": {
"a": 1,
"k": [
{
"i": {
"x": 0.833,
"y": 0.833
},
"o": {
"x": 0.167,
"y": 0.167
},
"t": 89,
"s": [-3.201, -3.166],
"to": [0, 0],
"ti": [0, 0]
},
{
"t": 118.000004806239,
"s": [-61.201, 57.834]
}
],
"ix": 2
},
"a": {
"a": 1,
"k": [
{
"i": {
"x": 0.833,
"y": 0.833
},
"o": {
"x": 0.167,
"y": 0.167
},
"t": 60,
"s": [26, 10],
"to": [0, 0],
"ti": [0, 0]
},
{
"t": 89.0000036250443,
"s": [1, 45]
}
],
"ix": 1
},
"s": {
"a": 1,
"k": [
{
"i": {
"x": [0.833, 0.833],
"y": [0.833, 0.833]
},
"o": {
"x": [0.167, 0.167],
"y": [0.167, 0.167]
},
"t": 118,
"s": [57, 126]
},
{
"t": 146.000005946702,
"s": [107, 69]
}
],
"ix": 3
},
"r": {
"a": 1,
"k": [
{
"i": {
"x": [0.833],
"y": [0.833]
},
"o": {
"x": [0.167],
"y": [0.167]
},
"t": 28,
"s": [18]
},
{
"t": 60.0000024438501,
"s": [60]
}
],
"ix": 6
},
"o": {
"a": 1,
"k": [
{
"i": {
"x": [0.833],
"y": [0.833]
},
"o": {
"x": [0.167],
"y": [0.167]
},
"t": 0,
"s": [48]
},
{
"t": 28.0000011404634,
"s": [100]
}
],
"ix": 7
},
"sk": {
"a": 0,
"k": 0,
"ix": 4
},
"sa": {
"a": 0,
"k": 0,
"ix": 5
},
"nm": "Transform"
}
],
"nm": "Rectangle 1",
"np": 3,
"cix": 2,
"bm": 0,
"ix": 1,
"mn": "ADBE Vector Group",
"hd": false
}
],
"ip": 0,
"op": 900.000036657751,
"st": 0,
"ct": 1,
"bm": 0
}
],
"markers": [],
"props": {}
}