Common shared element use cases
Stay organized with collections
Save and categorize content based on your preferences.
When animating shared elements, there are some particular use cases that have
specific recommendations.
Asynchronous images
It's common to use a library to load up an image asynchronously, such as when
using Coil's AsyncImage
composable.
For it to work seamlessly between two composables, its recommended to set the
placeholderMemoryCacheKey()
and memoryCacheKey()
to the same key as a string
derived from the shared element key, such that the cache key is the same for the
matched shared elements. The new shared element will be using its match's cache
as the placeholder until it loads the new image.
The typical usage for AsyncImage
is as follows:
AsyncImage(
model = ImageRequest.Builder(LocalContext.current)
.data("your-image-url")
.crossfade(true)
.placeholderMemoryCacheKey("image-key") // same key as shared element key
.memoryCacheKey("image-key") // same key as shared element key
.build(),
placeholder = null,
contentDescription = null,
modifier = Modifier
.size(120.dp)
.sharedBounds(
rememberSharedContentState(
key = "image-key"
),
animatedVisibilityScope = this
)
)
Text
To animate fontSize
changes, use Modifier.sharedBounds()
, resizeMode =
ScaleToBounds()
. This transition makes the size
change relatively fluid. The contentScale
parameter can be tweaked to animate
a specific font weight or style.
Text(
text = "This is an example of how to share text",
modifier = Modifier
.wrapContentWidth()
.sharedBounds(
rememberSharedContentState(
key = "shared Text"
),
animatedVisibilityScope = this,
enter = fadeIn(),
exit = fadeOut(),
resizeMode = SharedTransitionScope.ResizeMode.ScaleToBounds()
)
)
TextAlign
changes are not animated by default. Instead, use
Modifier.wrapContentSize()
or Modifier.wrapContentWidth()
over using different
TextAlign
for shared transitions.
Content and code samples on this page are subject to the licenses described in the Content License. Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
Last updated 2025-08-26 UTC.
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Missing the information I need","missingTheInformationINeed","thumb-down"],["Too complicated / too many steps","tooComplicatedTooManySteps","thumb-down"],["Out of date","outOfDate","thumb-down"],["Samples / code issue","samplesCodeIssue","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2025-08-26 UTC."],[],[],null,["When animating shared elements, there are some particular use cases that have\nspecific recommendations.\n\nAsynchronous images\n\nIt's common to use a library to load up an image asynchronously, such as when\nusing [Coil's `AsyncImage` composable](https://coil-kt.github.io/coil/compose/).\nFor it to work seamlessly between two composables, its recommended to set the\n`placeholderMemoryCacheKey()` and `memoryCacheKey()` to the same key as a string\nderived from the shared element key, such that the cache key is the same for the\nmatched shared elements. The new shared element will be using its match's cache\nas the placeholder until it loads the new image.\n\nThe typical usage for `AsyncImage` is as follows:\n\n\n```kotlin\nAsyncImage(\n model = ImageRequest.Builder(LocalContext.current)\n .data(\"your-image-url\")\n .crossfade(true)\n .placeholderMemoryCacheKey(\"image-key\") // same key as shared element key\n .memoryCacheKey(\"image-key\") // same key as shared element key\n .build(),\n placeholder = null,\n contentDescription = null,\n modifier = Modifier\n .size(120.dp)\n .sharedBounds(\n rememberSharedContentState(\n key = \"image-key\"\n ),\n animatedVisibilityScope = this\n )\n)https://github.com/android/snippets/blob/7a0ebbee11495f628cf9d574f6b6069c2867232a/compose/snippets/src/main/java/com/example/compose/snippets/animations/sharedelement/SharedElementCommonUseCaseSnippets.kt#L47-L64\n```\n\n\u003cbr /\u003e\n\nText\n\nTo animate `fontSize` changes, use `Modifier.sharedBounds()`, `resizeMode =\nScaleToBounds()`. This transition makes the size\nchange relatively fluid. The `contentScale` parameter can be tweaked to animate\na specific font weight or style.\n\n\n```kotlin\nText(\n text = \"This is an example of how to share text\",\n modifier = Modifier\n .wrapContentWidth()\n .sharedBounds(\n rememberSharedContentState(\n key = \"shared Text\"\n ),\n animatedVisibilityScope = this,\n enter = fadeIn(),\n exit = fadeOut(),\n resizeMode = SharedTransitionScope.ResizeMode.ScaleToBounds()\n )\n)https://github.com/android/snippets/blob/7a0ebbee11495f628cf9d574f6b6069c2867232a/compose/snippets/src/main/java/com/example/compose/snippets/animations/sharedelement/SharedElementCommonUseCaseSnippets.kt#L84-L97\n```\n\n\u003cbr /\u003e\n\n`TextAlign` changes are **not** animated by default. Instead, use\n`Modifier.wrapContentSize()` or `Modifier.wrapContentWidth()` over using different\n`TextAlign` for shared transitions."]]