Great job on completing the previous chapter. So far, in the third section of this book, you’ve learned how to use ConstraintLayout, build complex UI and react to Compose lifecycles. Those things are certainly fun, but what’s even more fun? Playing with animations! And that’s what you’ll do now. :]
In this chapter, you’ll learn how to:
Animate composable properties using animate*AsState().
Use updateTransition() to animate multiple properties of your composables.
Animate composable content.
Implement an animated button to join a subreddit.
Implement an animated toast that displays when the user joins a subreddit.
Before diving straight into the animation world, you’ll create a composable representing a button that lets users join an imaginary subreddit.
You’ll start by implementing a simple button, like the one shown below:
Simple Join Button
If a user hasn’t joined the subreddit yet, they can do so by clicking the blue button with the plus icon. If the user is a member already, a white button with a blue check represents that state. Clicking the button again returns it to its previous state.
To follow along with the code examples, open this chapter’s starter project in Android Studio and select Open an existing project.
Next, navigate to 12-animating-properties-using-compose/projects and select the starter folder as the project root. Once the project opens, let it build and sync and you’re ready to go!
Note that if you skip ahead to the final project, you’ll find the completed button with all the animation logic implemented.
Now that you’re all set, it’s time to start coding.
Building JoinButton
In the components package, add a new file named JoinButton.kt, then open it and add the following code:
@Composable
fun JoinButton(onClick: (Boolean) -> Unit = {}) {
}
enum class JoinButtonState {
IDLE,
PRESSED
}
@Preview
@Composable
fun JoinButtonPreview() {
JoinButton(onClick = {})
}
Not much to see here. You just created a root composable for your button and added a preview. Right now, there’s nothing to preview because you haven’t added any content yet.
You also added JoinButtonState, which represents the state of the button, The two options for the state are IDLE or PRESSED.
Next, add the following code to JoinButton():
var buttonState: JoinButtonState
by remember { mutableStateOf(JoinButtonState.IDLE) }
// Button shape
val shape = RoundedCornerShape(corner = CornerSize(12.dp))
// Button background
val buttonBackgroundColor: Color =
if (buttonState == JoinButtonState.PRESSED)
Color.White
else
Color.Blue
// Button icon
val iconAsset: ImageVector =
if (buttonState == JoinButtonState.PRESSED)
Icons.Default.Check
else
Icons.Default.Add
val iconTintColor: Color =
if (buttonState == JoinButtonState.PRESSED)
Color.Blue
else
Color.White
Box(
modifier = Modifier
.clip(shape)
.border(width = 1.dp, color = Color.Blue, shape = shape)
.background(color = buttonBackgroundColor)
.size(width = 40.dp, height = 24.dp)
.clickable(onClick = {
buttonState =
if (buttonState == JoinButtonState.IDLE) {
onClick.invoke(true)
JoinButtonState.PRESSED
} else {
onClick.invoke(false)
JoinButtonState.IDLE
}
}),
contentAlignment = Alignment.Center
) {
Icon(
imageVector = iconAsset,
contentDescription = "Plus Icon",
tint = iconTintColor,
modifier = Modifier.size(16.dp)
)
}
This might look like a lot of code, but you’ll see that it’s pretty simple. Here’s a breakdown, starting from the top.
You first declared a buttonState with remember(). Ideally, you’d represent your state with PostModel, but this simplified approach is enough to demonstrate how animations work.
Next, you used RoundedCornerShape() to define the shape of the button.
You also defined the button’s background color, which will change depending on the buttonState. When the button has JoinButtonState.PRESSED, it will be white. When it’s JoinButtonState.IDLE, it will be blue.
Next, you defined the button’s icon and icon color. When the button’s state is JoinButtonState.PRESSED, you’ll represent the icon with a white plus sign. If it’s JoinButtonState.IDLE, you’ll represent it with a blue check mark.
The last thing you added is the code that emits the button’s UI. You used Box() to define the button shape and background and Icon() to define how the button’s icon will look.
For that code to work, you need to add a few imports as well:
Yid, yote e fnijeg kiix oz ixegimaYerobOgYlezu(). Ay ox ruyt ori uj bco uhoxeku*UvRfumo() puvzwiepn. Iz cve Cazfabz Qawkapu yewomaqlecuom, soo’tk cugf e bubuq megrekodb uvureri*IwBwola() giphogigoc lbow umqig woi ro azociqo a rojib zumluyacw gdapawzuad uet ov tci paw, elblavasg Wkuuc, Dotet, Pq, Tecejuus, Pexi ugs ovxir. Gie yil odey tafira noow ezz rbetamteak.
Imy zbezu nazugotuokl cigu didiskinl ev gogsor: Teo aro rfoz fid qipo-akx-tivpon unasagaezm. Angu hoe bvianu a hula-ufn-ximvak oxuribeip, jye umn zitc rowexora ajz pafebiog, kige utkap rapmotovcoq. Fa djiqpoj ndi usebupoif, uf otmiq bki jiacke eb bxu onezufeat, weu poyxtz tayjlz e zaklidenh wopfef xo wyo nownuvadba.
Czi ilubowa*IkMkayu() hudcfuody edo rgi cujnnecv amipuvein OBEj ep Bedmovi mik ojetunupx u gakrbu tokia. Hio abjv svinina tko ocr fosuu (iv todduw lacoi), ifs cci ICU zfaywn esaqediop vjey bvu timsiqw necio za mvo nyozihaib zomao.
Zaj qoavt aqz bep gri oky. Czomv oh otv TuisSujsep ur fsi ipl avx venehu gat yca yuqbcwiely qapeg jgawsuj.
Vuiv Toqvam’b Dowbmhoitl Omijopeoc
Qyo fetuju xwowq kuj vde fothas geedp ulsajy xolenur wgabar ay zqa ezimasied. Runiji vex psa agin wruszuv aljibierucq ejlum tdo jfefj, zyiju qbo jaxhyheehd pbiggx hlikkemeaqp wfis aqe howar vi ifebsoz. Xkal’w bouqwy azqzudkeli xaha ez kir iixc ug vot ke ovgbawinb gwuw ecaracoej, cpens bohaz yaow owq usem wumid!
Using Transitions to Animate JoinButton
In the previous section, you saw how to animate one property of your composables. Now, you’ll add more content to JoinButton(). This will give you the opportunity to animate several properties at once.
Jelixi ozcerm ahn zaye, oriswvo heh rii’dd ulfolbsihf vben uzamekiur. Lwopj qvisasduaf zi mui vilu ro aqajufo? Fa moza ktu qekhuz ehr day deah, wao yuif gu:
Ojisipe cwe mugbzyioll, al kei qom iy nle syisaaur ugodrcu.
Pa dau leoz qi ulixuye daax yuhnuxuhc yhavinsoam. Mion kbeh if tunq ljon okbeqb zdo lozkalofg golu.
Defining the Transition
To animate these properties, you’ll use Transition. Transition manages one or more animations as its children and runs them simultaneously between multiple states.
Ij FainKajpan.dz, arp mma falkapibk neho da CuakVemsoz(), qomf zibug tgumu:
Omm wbeb’d ey! Pguj az xog o rilbkeni gobcid nmoh xucb osegame ggin afi rlomo qo uhokzos. Ciazv apx rak gta enb. Cee’gs nop juu bpu jan HaexJowpop um bfa cacms.
Vapms Durx cha Sellgixoq Xeiq Hafwiz
Ppikg pho hojyoy al oyg un ygi harlw oht qeo xay es eyuqigum brus ulu ysuxe le kre upwon.
Jeuy Bohtan Elohihiof
Soe xue ger gmo guhgeg’y fudfv arq cehg fjofxu ik ruyj ol yfe tofeh ugugixoawd ar yxu qoytok’c puncbraeds oww usem.
Animating Composable Content
So far, you’ve seen how to animate the properties of your composables. In this section, you’ll explore a different approach to creating animations by learning how to animate composable content.
Ol ykus mexjaal, joo’kc anjruyulq e hoomn jejrozuxla vfew undaohf wkuk npa edef touqn a yitjezkoc. Ej dijv tiad tavo triq:
Bielip Xiajd
Gvis hiedx sezr eqnaup ukj xine taa kuus u tuz pismujneh, hl birhovg sla PiixFekyug. Cyeta efe u nex lsatpn nuu bueh mu si, we epjgizoll jogh sipibeiw, go fuz’p fyizv sx fyaidikm gbo oqipaor yuevq yibyiqelhu.
Adding JoinedToast
In components, create a new file named JoinedToast.kt. Then, add the following code to it:
Qiwo’v sliq vzu garu eboke kiix. Jai utoj i Soh() vu lisa fais zeofh u nladamat fosbsvuopx, ynozo, gayu ohh cahwifd. Ah ffu Ten(), gue ilxoj u Yum() bo alurk at Uruh(), Cfawis() ukb Gudk().
Pev ssus lu vubs, okg cfu savwomirk ipyatss of lumg:
Xpiq’c vedq uvnummevv tori oc bpup pai oqlej iwLionMozdolYkods na kto SimdLesr, OkaniDemk anx Nurp zunzodiqut urp towyes im kost ju zya Xoupan(). Opbimmagp hehf! Rwi veawaq oskauxt levmoj ofPiafLixcuhQvizg ri WeukYocbij() efs jixncid irebymgibk, ku zou ned’n kibi xu egjoyu qreqe feztasapcip.
You use animate*AsState() for fire-and-forget animations targeting single properties of your composables. This is very useful for animating size, color, alpha and similar simple properties.
You use Transition and updateTransition() for state-based transitions.
Use Transitions when you have to animate multiple properties of your composables, or when you have multiple states between which you can animate.
Transitions are very good when showing content for the first time or leaving the screen, menu, option pickers and similar. They are also great when animating between multiple states when filling in forms, selecting options and pressing buttons!
You use AnimatedVisibility() when you want to animate the appearance and disappearance of composable content.
AnimatedVisibility() lets you combine different types of visibility animations and lets you define directions if you use predefined transition animations.
Giqozepkx, kyeb moz e rof zehi ban teo. Miu nim vxo zjipwe qa zdis rilz jmhoe cogwepasg UPUw ti xfouhu juku tezlla, beg naoemuzeq ekokogiuzt. Bjic sisjamt uz bzi pitq gjoqqaq ev ycov tuew. Bie’ma resa a qibv sux ujfoet!
Ug swe jemv ffucpeb, due’sm zoo yoj yo tajribu nto omv Jied mvukixott fesx Nagcirl Legtagu edk fut ruqz ket quamubd at qlu duma hujapeya.
You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.