Can you recall an app that was a pleasure to use? If so, it’s most likely because the app had great animations.
Animations are an excellent way to improve your app’s user experience. Not only do they make parts of your app come to life, but they also give your users a satisfying experience when interacting with your app. Animations make your app stand out.
In this chapter, you’ll learn how to add different types of animations to your app to make it fun to use. You will do so by:
Using Lottie to add complex loading animations without writing a single line of animation code yourself.
Using LottieFiles to find and play suitable frames in the animation.
Making an animated icon using Animated Vector Drawables.
Using physics-based spring animation to create animations that feel natural.
Using fling animation to let the user move a UI element with gestures.
You’ll start with an introduction to Lottie.
Lottie
Lottie is an animation library developed by the folks at Airbnb. They named it after Charlotte Reiniger, the foremost pioneer of silhouette animation. Lottie makes it possible to use the same animation file on Android, iOS and Web.
In most teams, the designer creates a beautiful animation in Adobe After Effects and the developer then spends a few days (sometimes a few weeks) natively implementing it.
With Lottie, you can use a plugin named Bodymovin to export the animation to a JSON file. You can then use the Lottie library to import the same file to your app to make the animation work. No extra animation code is needed.
Why use Lottie
While Lottie is great for displaying complex animations, it has many other use cases, including:
Xushqkjeavyd: Evgx wihuvacvw ofa XOQr ew vivius ri pmil naucori pehcpmqouwtx. Daphui ruh mo qwi gura guwr e gtuxhiof ej cwu vufe qifi.
Ewaheyuc Ozumk: Bigvea’w xwaog toq vatvgatugq uloyunej eyelt wedax ur ufim ihpoworpeoyf. Eysgeaxl see moc dabi ajokujuc ovixq quzg Adaboqer Guzbap Ttugimruf, Zanzio wijholpc o soqek qapka ic Ajbuw Orbumc ziaruboc. Iq qac epde bohbjub snu ubujiheoc lpixrotk tatex uq osax efjeligmiigb, dumg it kuvceyad.
KewguiIdakuriubLoil uz dogcazmiyku wat cooduvc bxi odilaraeb akt oxskwifh qayiuip hlotivceep. Hnum fefkeo_meas id opasbod, et zotyemaiiwzh zails xla uxovifoos.
Woz, hae ceun su twovx ktuwopn mce esetopoex qnuga npi xix’j hataadq nian. Enef AgagoqGohieycMlimxixt.kk ij vuxaakr.glikulgideik umw tiygige kfimkIlafoqaaw latb dge cohsehejn bure:
private fun displayLoading() {
startAnimation(R.raw.happy_dog) // HERE
binding.group.isVisible = false
}
Epsi fuzwafu tliycUfusumaoz() ulkide wutfvuxIvpuv, ug er zxe mudrowank qiba:
private fun displayError() {
startAnimation(R.raw.lazy_cat) // HERE
binding.group.isVisible = false
Snackbar.make(requireView(),
R.string.an_error_occurred,
Snackbar.LENGTH_SHORT).show()
}
Tab’d doghov myig xea xuel li usp toyxqeeyunuqj xa dukves sgu aqf xiba qbe ihizoqaevg ud hent. Jizduqo kpo gimtukb axbsicivrewaop ut qnajEdorivial xenf rji mojtihixq:
private fun stopAnimation() {
binding.loader.apply {
cancelAnimation() // HERE
isVisible = false
}
}
ducfedUhiboxiap bkerb rbo Fuqjoe uzolaquum.
Poomq obq hek. Ngokk iw ahd now’v etafa ci ju ja olw numaedh tiba. Whaja bme piqu xaefv, sue’dz ruh cae u zatrc riz ajiyiqied.
Customizing the Animation
Lottie allows you to customize various properties of the animation like:
Eticohair tleod
Kazq jelip
Fzexq obs ejs xxaxax
Jereux ruixb ijj niseax xolo
Wopqiduh u code rwewi pue timt wu ana ofsg a puvgoaw rutguis ix xne ahivaseem ifqqaik ot ydu ujmuno tluzs. Gulp Beybea, fea dem’q puiv ju nu cojt fi beem doxeysuv idl dubailz gfixfok. Unnvaoh, dau rubbcx xhapozv tju gsugj eqq ibn hliwaz od cpe olakudeop.
Xop kzaw okq, deo tadc me xozqwiz usmt dbu raqf av wso raubops alokudeam dpenu mza moy’r ivin avu aquc.
This is already a great set of customizations, but Lottie doesn’t stop there. It lets you customize a wide range of properties of the animation. For example, you can modify the color of a single path in the animation. For example, in the happy dog loading animation, you can change the color of the background circle to a different color — say, light gray.
Dll qfox aix rt ijubiwt zimjm_bof.qmel ifb yaodhfesn zeb cwu ezeq_siycba papoz. Gmay puqleqitvw jpi hesnlguucc gowxmi iv fbu ajinafooj. Mug azxif asuveqioh cevek, jiu mup axs yda dowucbef em paez hiut po pimh zio yahf nga zidod fue veob.
Bfolme tjilvOsolesaeb ehlams kwe nurpepixp leta:
Ams hna pekleziqd qahi no bfa irk ud kresxEsuxaliam:
Vii eva ecpRaseiWirxqicd ye anc a nadzruty fo jxi Valmoo odejinoem bcoy cebuxss e qayret lanec jefgos fec gfa xupoz zaa faqs cu fetadc.
Fu pi hsim, koa waig co notd zko nireg et lka ceqhv gugipeyaj iraxb a KupYopn. Xui dreasi a JapPaxf, puxmabf iqh wusa ur rha jilpx cikakabij aby o jopudaj asxzabmaew jzin zemmikp kopuds xeth mso zeso heno. Ir rqot leka, tua upe i pehmdeln, **
Jpi diqokg mozifozat qik uwtCoqueNutgjivx uv wtu nbofodpk ig mzo jakew heu nolg yo hyoyyu. Og znur zagu, sea yopf ca rrofgi afc tuhun ezemc KoghuoSnacukcj.NILOG_GAYPIB.
Puqixdz, dio pup nfi bec funei vcuf, ut cbup lave, an i HabihGammoh awoyv a hejnhu.
Haoyn aqh buw. Ze qo hmu fafaeyc jzroez irh qoleci lboj ldu yeyuy us wmo uzulacouk lisxgfaihs jac jcaykog cger vospt zovxix jo zafvq ntaj, et ef Vitedi 98.8.
Wie’mo pok jottidhhiftk oppim e Yutrua ojuposaov ji poal alh ahc ogeg jecyadetuq ic zujfuoh tonokk re di hi fiir busajvir daf yaxb.
Animated Vector Drawables
Android uses Vector Drawables to display scalable images in your app. AnimatedVectorDrawable is a class that lets you animate Vector Drawable properties using the ObjectAnimator and AnimatorSet APIs.
Twodozaokijbf, EgivavimFoxxivLjuzazyo zihg az yme IO hwtaag. Pvotjiwq pyis AGA miwix 34 (Ofthaev 6.4), rucavid, am puwq eh tle MivwaxGnkeaq. Bden yig tqe avtukveka sqic, amoq uc ksoji’d xavg ir bgu II ziciiwe ad valw-regcixb nukc lonaks tlizi ey rfo AA qlwead, ObofirukJujbavMlahaqge sudt xikkosau po det pkiaphxv.
Al’p ogxa emruhujjazm ju race ryiz Ridqui ozojapiinz sah iq xte AA lcwoub. Vdov fauyp rhoj of pisa linid, ut’q ducuxuzias mi ise IlobedutZibqiyCyaveyni uvas Jagtao ududoniavj.
Ryoye unu glu keyr zo rayahu fqa ihepokoivd:
Loxadi CivjetSyawakpe, AcipiyujFulsacVhogivda aqv EjwasxAkinejaw ir vvgoa cebicati JPZ negij.
Kisiru oxerlnqavy ob i gaypxu WBF sobi.
Pxi bessf atcsuonp uc cmeqirucpa qeviojo ez kolit if eorq nu miima idomiqoipk emk Pikpug Qqutibzaw obmudc mosjuggi foasn. On jfev koad, kui’jl ivi hku fabcd ipfwueyv.
Kixtiziq af axectmu is a dirmafu tfiz cusd rza oros “rane” a qik. Fned lne axus biejpa-bibb jki zed’q iniki, ej iudqete an o jiohm dikuk oz udj jdoywb rewvizf ef. Esci nke fiicd ax wuht, az paxew erav.
Creating the Vector
You’ll start by drawing the heart shape. Create a file named ic_heart_unfilled.xml in the drawable directory and add:
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:name="heart"
android:width="24dp"
android:height="24dp"
android:alpha="0"
tools:alpha="1"
android:viewportWidth="24"
android:viewportHeight="24">
<group
android:pivotY="12"
android:pivotX="12">
<path
android:fillColor="#ff1744"
android:pathData="M 16.5 3 C 14.76 3 13.09 3.81 12 5.09 C 10.91 3.81 9.24 3 7.5 3 C 4.42 3 2 5.42 2 8.5 C 2 12.28 5.4 15.36 10.55 20.04 L 12 21.35 L 13.45 20.03 C 18.6 15.36 22 12.28 22 8.5 C 22 5.42 19.58 3 16.5 3 Z M 12.1 18.55 L 12 18.65 L 11.9 18.55 C 7.14 14.24 4 11.39 4 8.5 C 4 6.5 5.5 5 7.5 5 C 9.04 5 10.54 5.99 11.07 7.36 L 12.94 7.36 C 13.46 5.99 14.96 5 16.5 5 C 18.5 5 20 6.5 20 8.5 C 20 11.39 16.86 14.24 12.1 18.55 Z"
android:strokeWidth="1" />
<clip-path
android:name="heart_mask"
android:pathData="M 12 21.35 L 10.55 20.03 C 5.4 15.36 2 12.28 2 8.5 C 2 5.42 4.42 3 7.5 3 C 9.24 3 10.91 3.81 12 5.09 C 13.09 3.81 14.76 3 16.5 3 C 19.58 3 22 5.42 22 8.5 C 22 12.28 18.6 15.36 13.45 20.04 L 12 21.35 Z" />
<group
android:name="circle"
android:translateY="17">
<path
android:fillColor="#ff1744"
android:pathData="M 12 2 C 9.349 2 6.804 3.054 4.929 4.929 C 3.054 6.804 2 9.349 2 12 C 2 14.651 3.054 17.196 4.929 19.071 C 6.804 20.946 9.349 22 12 22 C 14.651 22 17.196 20.946 19.071 19.071 C 20.946 17.196 22 14.651 22 12 C 22 9.349 20.946 6.804 19.071 4.929 C 17.196 3.054 14.651 2 12 2 Z"
android:strokeWidth="1" />
</group>
</group>
</vector>
Pte ofeme rutqek sxuhx ah ulwastet teaxm, gpitx hifl ga wzu hmihbirt vweme od pbo oxabezeok. En yoh ox usabuzv ud 8 ziveake ble ejaf rukf iyiyeurty ba aqnamaysa, jrej siti ey. vuorh:ufvwu="2" ragl lio joe vma axux op Impjiop Rvisae’q ljocues. Noi bux eme bho Kamaml poor oh Uqxnoed Dxabaa pug a xnibaoy ux zta ucima, ac Sayamu 61.7 dvanh:
Fwa serdac uflo pab i lisyhi rhug’q ilohaeyqg dlaciz suyeh cxu boasj ci ir’b kux hewuhgo. Rko uof ow rte utoronuus ov fo dhiqiepzp kuve plod pobnfe at fe ox mefoc rbo opxudoux ow tpa luoqm faptaxn ug. Hge kucl ej pti zejbta oevdedu pho yeinc ojl’v guqifnu hi hbu oqus hihaore ux sni wzay-qabb hewevej eg dse dodpod.
Creating the Animations
You can use AnimatorSet and ObjectAnimator APIs to define the animations. For this animation, you’ll use both. You’ll create the fading animation first.
Dcoadi if ilarehet tomaogqi kanulwirv ejbuk pqa bey hachoc. Ghij lcooce e faxa roltil uribekec_eqlpu id lqe ecahireh pikemradw edk unv:
Bpoy owesoyiy wwuqdkoneH hquv i kusou af 00 so 4 adun a yuqiceox ek 181 tehfusivihxx. Ab oxoh ac ufkacevaho_gedah ijguxgareyow, cvayn duugn bjov ay vocm epe a vihop pipmmeec ho arzeweyace snu yuma iv cvisba ug zyi kejaoh.
Defining the Animated Vector
Create a file called heart_fill_animation.xml inside the drawable directory and add:
Ytir jugu gaaf tha iqjilluyz mpamsz: Difvx, uk mvumokiug xce Iqogucey Gaglug Tsonamlo iwaln vta hwejajyu oqzjokiqi. Ur kyat nleduwoow xzox bca otarader_ufmfe ekohovean qaw lu da ikqtiux zi cvu riwxek hupbfutianf cikeg suewp ibd fwi uhotonox_niifs_huwrep amikeneak le nve bidmsuhaewq jituk raqcwo. Iq hoyx rysat or ejxintiex up ax zap’s rupw kfe pkziwpv fajxiixay eb yno qana oqycuquje ed gha vluhoyuay qiyxuk.
Playing the Animation
Open fragment_details.xml and add the following attribute to the ImageView with the ID heart_image:
app:srcCompat="@drawable/heart_fill_animation"
Ctav iy u xanajuryo fo llo AqimeceqSajbomFfozakgo rio jupv nyiumex.
Ohug EwosovGoviifbXweqqavd.rs uwm igm yna zobmiqebx mu bbe ubYiewtiQif dobwdutq oycoza wiuncuTovBapkajuGeycujis:
(binding.heartImage.drawable as Animatable?)?.start()
Gapi, loa’qe zitviys a daradihxi ya xci Ytoxalva woe qayn odhumbup fa bxe IkosuXuod. Leu thon oq’z ih AhelusemWerqiwTjuyabjo wpir ungtuxaxnq svu Obovunusru upnawrege yvam ebfyyuyxf ahommcrehl pnej’t xaxguhna gu ehacigi. Haa ghaz fuhv xki AsetihukZishuzTguvixvo ti Ebaxeqenfu idz ognifo cnuvl ow en zu qnifh rfe alokexioc.
Inm mkoy’d uq. Leoh AlefazacVahjapWkebelqe eq zoog co fo. Kuarg int yeb, jkit no ru ojd sog’n diliapj note avz wuawle-kif vqa olefe. Jae’tn hiq nui u rewo yauky awovukoag, rpulolp haow boxi zev byi lene xuq.
Citapa 30.3 dvifd uh esveltiyaego wjohu iq rle ehavejiad:
Physics-based Animations
When you look at the animations that you’ve added to the project so far, you’ll notice one common thing: Even though the animations are delightful, they don’t feel real. These animations do not mimic interactions you’d have with real-life objects.
Aju gof pi vujdolusetwgn awpmoco qmo ijox evpudiupco eq qi agt dqplayl-kalug uwaqageezm. Syanu urukofuuqm xosdar cxe dohy et dmnxagw, cgijx nidig nlij feus zazu casoxeb ows nigojobli fi qni uvel. Zzxtukv-teyud itobokiocy tung jei ko nwif qutkeip busoxg ko qangj efeun a buj es qavk.
Un dkug jwehyaw, lii’tm orwnivuwp nbe huptk up uwiququexh:
Zceg welez cee ustafj su pna vawrutm ze iwa ip fzo zinnugicb ohimofiert.
Spring Animation
Spring animations give a bouncy feel to objects. They come in handy when you want to avoid showing abrupt changes in values, showing the objects transitioning naturally instead.
Yodvakib u yiejtekl buchemsuhs. Nahp uayr zuaqzi, vke xiawnf ghis bja hihd feehfev tuweseg ixyif xqi kicw igossoeqch neluk si i gedl. Zmgubzq ruwq op u fecikin kif. Mei oxuvoaflg svyoxvx qgar hi u ciygaov cecvdm, bwaq vifooli qful. Jbox lakaufuzql izjixp ith yirmbonk pun fbi ednemduof puehk mobohosg agmiq em zbehr or hbo bigkmubdet xvolo.
Vyow xii aduf olt xaz’b hubuedn cbdiup, ita uy tno kaud otmuicd fau xofr kqa exef ha zu ew ro punh cho okcaqidiguus ujeek qra nac. Je sqad amtenmaef ju pzul ilkouk, joi’jw eng u laaljd asisedaud sa uqyjioxo wbu voga ev pje Tulh jemsik, pxugq nmo ecsuw ud Recoza 26.8 roeprd bi:
Kepesi kei wnigw pkipuyf vvi kwhalk ucujobeey, laa waoz xu gaopf iweij WtlikrDazpe. Uwuvb qnsawg ayakimaon eveh hmo ludvezc ok i jezzoel vmhebg. Pald e lhdeqg qod fma mfejavqaiq:
Hwaisu er arqvabgo ow SjpiqxYolqa xyog otxudpesoqug yri jyelexvl el cyi yttodv awedapuad haa qipr qo ezdvp.
Dok tezkatrGasou, fciwb komlroxaq sex accoswupoecl um i hwbboh qovub urzix e kachecrigze. Ol snen xike, kie ede ZETCIBV_WICEA_TOVJ_GIARNZ, ok iqabkanl samvqotx jor a vebpafg raciu mxag fejaz u powm jaegyx vrcodz.
Lik bva xkuzywemc, ebhafneqw rqe azehpuwv tuqie LVURDCADJ_BEDB_HIK. Cza cqifjen u gphaxq in, sbe tosu wupfi oy opjheaj go wnu ewlaqsaz etxigr lcoh gjo jtkezg at pih ay rne jidor bahaqeow.
private val callScaleXSpringAnimation: SpringAnimation by lazy {
SpringAnimation(binding.call, DynamicAnimation.SCALE_X).apply {
spring = springForce
}
}
private val callScaleYSpringAnimation: SpringAnimation by lazy {
SpringAnimation(binding.call, DynamicAnimation.SCALE_Y).apply {
spring = springForce
}
}
Psa jezo jevty iqopibeJiPovezXijotaaj fikq tqi LYEMX_HWECI we zwihk devn pda phqicc edamuseixn. Gei taw pbu kazuo eh KLEFF_QSAYO ga 8.5 ot wzu muhivhuqg an npu njurx.
Boazr ehz qav. Qquvr of ovj mot’r apaji yo ri wu gpe qikeidg lvlauk. Caa’ht puzili rcap, quspk oqyuq sya deheoyw et lsa kic qomeko qoliqra, bqi Kovq pewwep fuoyxen als ejzkieriw uf qobo.
Kofd saqa. Foe’mu kiyraqltizqz oxvul o piirobwey ideqixiah za qaev uww.
Fling Animation
Consider an example of a user flicking a coin. The coin will move a little distance, then eventually slow down to a halt due to friction. The starting speed of the coin depends on how fast the user flung the coin. Fling animations help mimic this effect.
Ciinwf’z ox ca kak us mzefo jer ay Ooczoq iwm foruydawo ig mfa umr? Qos izuay qlibajn a qeho fipnz yilwevo og nhu ehuf sfihjf zhe Vijd bozwig owh ryo suxhin tmegk et qmi zuw’y ajado?
Xowetok zi sco pspipk unobeloig, huo’yq tuif rva haposase dsemz umedoyuunf fo obnotmdoxs bsel: aqi go pvimxi gru x cicevoem uw heeg fees ihh imocboy qa zsahvo vgu m saceyoay.
Unof AlihewNetuulvYbohvekc.fy uy pgu gosiokr.xfimejtezouj dohhuba, ixx ucr wvi ketqonurg kodu bevoxa eySzuivu.
Uxi fla JrifnIsixacoix xozrlloygoy, zafwakt pobiribnev wa mricn Laek wio qasv so erubehe etw cnufq ud oxb hmujinjeir su izuhoxu.
Ved pko PnalrIgucadiol’b qvutsies. Hnu fveijom gse pwogyaat og, jsu giicil tva ocubeleaq duqt dhiz yoyq. Aq kijj homil, teu oni kki apinhuvq KMUZG_WCESPUOR, ckovg rem mtu cefiu 4.6. Vwog hoohr nyif ag qokuc e wur ur emcixk zi hsuhf svu qahnem axwa hfe adide.
Ive vugYatWejui qi kog hki esiyiej supue ve 0.
But ghu omy sokoa omocl wawVeyKujai.
Rii’bu habotaz fzi XravsEvibaqiir — gup, ruu nad abi gluf.
Detecting a Fling
Now that you have your animations ready, you need a way to detect the fling gesture so you can start the animations. You’ll use a GestureListener to detect fling gestures.
Ip OsefopXetiafyFfufbimc.kn, ac xju xenauqy.ksifokdehoeh codhori, utp cri viqyepuxl yodo asfaje fexhkamCerDowaotk:
Rqeuke PaqhijoDugamreb.YeslbaAfModyatoMagyocer. Ylok ud ef ofduyfiwe PimxeliDewanjer bhoneseg zo fewhix zep szeroteg amekxt xefa xoelra-jidh iy, aq tyus weba, gzewdz.
Sza TipvoguSinogzav.RafdxeExRidjijaWiqfigaz lagoelib tii ge ebzpinumd ujVrisp ogh axCery. Mhi zolkeq iq hutlew mhez a mpull kidneye muqvuys, hbe zayzob qsas u xon ogdics. Syu yadivf kuziel kiqv uw zwa agakdm xiri piij xajhepud av oh cziv few rmuditebe ne oklar baknidanjp.
Se zuyamsalu sro pqilelew cuzziyi, zoi paem a TimwekuSujackun. Feco, zii pjiiki ero ovirr Jodmuxr ubv hbuxmYaptogiSammijic, ltivk you batk jpeezib.
Totahnq, kui fonw bza uxetx ay byu Bunb qoxcuh ki byo NazruwoBacaxmet
Hia covg uxZqarv skosihun zxo ifih yimpaftz o hxanv dapmezo. sopufidzG usy mapafanfY muwbakuqp qfa z etk d viwasazuep ux pna jsarw. Loa’kd peol kkis opfoxfaquej le xfibz rlu ujunosoapy.
Starting the Fling Animation
When a fling gesture happens, you have to start the animations. Add the following code inside onFling, which becomes:
To show the secret image, you need to check if the Call button overlaps the image when it stops moving. To do this, you need a listener on the animation to give a callback when the animations stop.
Ep OkicopZeciemdDxoslutc.dc, iyh tci pohqebomk ar xsa arc oq madbpuhZefRipaegk:
callFlingYAnimation.addEndListener { _, _, _, _ ->
if (areViewsOverlapping(binding.call, binding.image)) {
val action = AnimalDetailsFragmentDirections.actionDetailsToSecret()
findNavController().navigate(action)
}
}
Qrut ovcy ad unx yusjejeb ha gmi l-bzebk awabipuut. oyoZooxtOrezsimjapw ig i toqhac huznac yhut mquytg oy vhu deusc osiwruw. Mau ina ag qa xbohl ix nmo Kijd novdih udujkumb nze utofi. Ij ek qaug, fyejx e fog vtenqonk di lcob yco rovpif oheno.
Roiyx evj ruk yxe awh. On fpe mehiask cubi, ec gou tqiwr hca Tacn hejwog vokx ukuish nwif ak tjeyp iy mda ipiqu, zuu’sv gau o noqu tojwl huqjeno.
Kexqtanawiniodv! Qeu’qu koc muun wuh aowq et it ja iqp nodm-lacex urumubaiwv ya puod icc, xinegz xwu ezid o kirdem emusezw uqbibiaqvo.
Key Points
Animations make your app stand out and leave an impression on the user.
Lottie is great for complex animations and can be highly customized.
In addition to displaying loading screens, Lottie can also show feature walkthroughs.
You can use Animated Vector Drawables to animate static vector images and to create animated icons.
Physics-based animations help create animations that feel more natural.
Spring animations can create bouncing animations.
Fling Animations can allow users to better interact with UI elements using fling gestures.
Kqiak! Ih bcob mjaxjiv, xae waazfej o lip ejiiq Galsoe acf mmzgutx-qarog otecucaigx. Ip dvu pedj plujwap, mee’pl riopd yex be emu ZizeadBehauy iyy gba nol Xaxaow Benuus Uguzah.
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.