Posted by Rebecca Franks – Developer Relations Engineer
Androidify is a brand new pattern app we constructed utilizing the most recent finest practices for cellular apps. Beforehand, we lined all of the completely different options of the app, from Gemini integration and CameraX performance to adaptive layouts. On this publish, we dive into the Jetpack Compose utilization all through the app, constructing upon our base information of Compose so as to add pleasant and expressive touches alongside the best way!
Materials 3 Expressive
Materials 3 Expressive is an enlargement of the Materials 3 design system. It’s a set of latest options, up to date parts, and design techniques for creating emotionally impactful UX.
It’s been launched as a part of the alpha model of the Materials 3 artifact (androidx.compose.material3:material3:1.4.0-alpha10) and comprises a variety of latest parts you should utilize inside your apps to construct extra customized and pleasant experiences. Study extra about Materials 3 Expressive’s part and theme updates for extra partaking and user-friendly merchandise.

Along with the brand new part updates, Materials 3 Expressive introduces a brand new movement physics system that is encompassed within the Materials theme.
In Androidify, we’ve utilized Materials 3 Expressive in a couple of alternative ways throughout the app. For instance, we’ve explicitly opted-in to the brand new MaterialExpressiveTheme and chosen MotionScheme.expressive() (that is the default when utilizing expressive) so as to add a little bit of playfulness to the app:
@Composable enjoyable AndroidifyTheme( content material: @Composable () -> Unit, ) { val colorScheme = LightColorScheme MaterialExpressiveTheme( colorScheme = colorScheme, typography = Typography, shapes = shapes, motionScheme = MotionScheme.expressive(), content material = { SharedTransitionLayout { CompositionLocalProvider(LocalSharedTransitionScope gives this) { content material() } } }, ) }
A number of the new componentry is used all through the app, together with the HorizontalFloatingToolbar for the Immediate sort choice:

The app additionally makes use of MaterialShapes in varied places, that are a preset record of shapes that enable for simple morphing between one another. For instance, try the lovable cookie form for the digital camera seize button:

Animations
Wherever potential, the app leverages the Materials 3 Expressive MotionScheme to acquire a themed movement token, making a constant movement feeling all through the app. For instance, the dimensions animation on the digital camera button press is powered by defaultSpatialSpec(), a specification used for animations that transfer one thing throughout a display screen (comparable to x,y or rotation, scale animations):
val interactionSource = keep in mind { MutableInteractionSource() } val animationSpec = MaterialTheme.motionScheme.defaultSpatialSpec() Spacer( modifier .indication(interactionSource, ScaleIndicationNodeFactory(animationSpec)) .clip(MaterialShapes.Cookie9Sided.toShape()) .measurement(measurement) .drawWithCache { //.. and so on }, )

Shared ingredient animations
The app makes use of shared ingredient transitions between completely different display screen states. Final yr, we showcased how one can create shared parts in Jetpack Compose, and we’ve prolonged this within the Androidify pattern to create a enjoyable instance. It combines the brand new Materials 3 Expressive MaterialShapes, and performs a transition with a morphing form animation:

To do that, we created a customized Modifier that takes within the goal and resting shapes for the sharedBounds transition:
@Composable
enjoyable Modifier.sharedBoundsRevealWithShapeMorph(
sharedContentState:
SharedTransitionScope.SharedContentState,
sharedTransitionScope: SharedTransitionScope =
LocalSharedTransitionScope.present,
animatedVisibilityScope: AnimatedVisibilityScope =
LocalNavAnimatedContentScope.present,
boundsTransform: BoundsTransform =
MaterialTheme.motionScheme.sharedElementTransitionSpec,
resizeMode: SharedTransitionScope.ResizeMode =
SharedTransitionScope.ResizeMode.RemeasureToBounds,
restingShape: RoundedPolygon = RoundedPolygon.rectangle().normalized(),
targetShape: RoundedPolygon = RoundedPolygon.circle().normalized(),
)
Then, we apply a customized OverlayClip to supply the morphing form, by tying into the AnimatedVisibilityScope supplied by the LocalNavAnimatedContentScope:
val animatedProgress = animatedVisibilityScope.transition.animateFloat(targetValueByState = targetValueByState) val morph = keep in mind { Morph(restingShape, targetShape) } val morphClip = MorphOverlayClip(morph, { animatedProgress.worth }) return this@sharedBoundsRevealWithShapeMorph .sharedBounds( sharedContentState = sharedContentState, animatedVisibilityScope = animatedVisibilityScope, boundsTransform = boundsTransform, resizeMode = resizeMode, clipInOverlayDuringTransition = morphClip, renderInOverlayDuringTransition = renderInOverlayDuringTransition, )
View the full code snippet for this Modifer on GitHub.
Autosize textual content
With the most recent launch of Jetpack Compose 1.8, we added the flexibility to create textual content composables that routinely alter the font measurement to suit the container’s accessible measurement with the brand new autoSize parameter:
BasicText(textual content,
type = MaterialTheme.typography.titleLarge,
autoSize = TextAutoSize.StepBased(maxFontSize = 220.sp),
)
That is used entrance and heart for the “Customise your personal Android Bot” textual content:

This textual content composable is attention-grabbing as a result of it wanted to have the enjoyable dancing Android bot in the course of the textual content. To do that, we use InlineContent, which permits us to append a composable in the course of the textual content composable itself:
@Composable personal enjoyable DancingBotHeadlineText(modifier: Modifier = Modifier) { Field(modifier = modifier) { val animatedBot = "animatedBot" val textual content = buildAnnotatedString { append(stringResource(R.string.customise)) // Connect "animatedBot" annotation on the placeholder appendInlineContent(animatedBot) append(stringResource(R.string.android_bot)) } var placeHolderSize by keep in mind { mutableStateOf(220.sp) } val inlineContent = mapOf( Pair( animatedBot, InlineTextContent( Placeholder( width = placeHolderSize, top = placeHolderSize, placeholderVerticalAlign = PlaceholderVerticalAlign.TextCenter, ), ) { DancingBot( modifier = Modifier .padding(prime = 32.dp) .fillMaxSize(), ) }, ), ) BasicText( textual content, modifier = Modifier .align(Alignment.Middle) .padding(backside = 64.dp, begin = 16.dp, finish = 16.dp), type = MaterialTheme.typography.titleLarge, autoSize = TextAutoSize.StepBased(maxFontSize = 220.sp), maxLines = 6, onTextLayout = { consequence -> placeHolderSize = consequence.layoutInput.type.fontSize * 3.5f }, inlineContent = inlineContent, ) } }
Composable visibility with onLayoutRectChanged
With Compose 1.8, a brand new modifier, Modifier.onLayoutRectChanged, was added. This modifier is a extra performant model of onGloballyPositioned, and contains options comparable to debouncing and throttling to make it performant inside lazy layouts.
In Androidify, we’ve used this modifier for the colour splash animation. It determines the place the place the transition ought to begin from, as we connect it to the “Let’s Go” button:
var buttonBounds by keep in mind { mutableStateOf(null) } var showColorSplash by keep in mind { mutableStateOf(false) } Field(modifier = Modifier.fillMaxSize()) { PrimaryButton( buttonText = "Let's Go", modifier = Modifier .align(Alignment.BottomCenter) .onLayoutRectChanged( callback = { bounds -> buttonBounds = bounds }, ), onClick = { showColorSplash = true }, ) }
We use these bounds as a sign of the place to begin the colour splash animation from.

Study extra pleasant particulars
From enjoyable marquee animations on the outcomes display screen, to animated gradient buttons for the AI-powered actions, to the trail drawing animation for the loading display screen, this app has many pleasant touches so that you can expertise and be taught from.



Try the total codebase at github.com/android/androidify and be taught extra in regards to the newest in Compose from utilizing Materials 3 Expressive, the brand new modifiers, auto-sizing textual content and naturally a few pleasant interactions!
Discover this announcement and all Google I/O 2025 updates on io.google beginning Might 22.