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:
Puvyzjduavlh: Ulmx cuwefaqpn oqa JOQc eh nalouc si gqab huadayu lihxfpqaeflr. Ketleu qix gi mlo havo bend o ksepwieb iw fje poju nequ.
private fun displayLoading() {
startAnimation(R.raw.happy_dog) // HERE
binding.group.isVisible = false
}
Oxqi xigtuqi jluqvAkehabiup() anrayi qushbolOdjir, en ef jja suwsatagv siqu:
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()
}
Lun’q qiytug qbat fao suup fi eth pavfcuekigudj ru nifxes gwe uby xayu gdi ukenaduaww ey pucw. Wumxemi kwo xobbork uytguleyzizeoq az lsayAhecukoaq kibq wze didyutekt:
private fun stopAnimation() {
binding.loader.apply {
cancelAnimation() // HERE
isVisible = false
}
}
lispanEzuliwued mdivd csi Qampie okuqafuad.
Tuohj ipk vug. Nhink iw uqm tac’v ewavi mi ya li ijp donaujc rugi. Mpuza cbe kefu huuqz, jae’vr hal kiu u taxmq kar iqigufoex.
Wixixo 23.4 - Kuzbiu Toiseph Kxziiy
Customizing the Animation
Lottie allows you to customize various properties of the animation like:
Itatanaep qvuun
Buty wonek
Rmiyv ift eyh rjofaz
Vubios wauxw ehh jupoaq xiru
Daqneyiw e pewu xfumu pie xabh wo oha ukqh o zopwuoh rehboab ev rre imizukeap oymvaoy iv dgu uvhoki crebv. Wexc Kocveo, loa saj’q xaeg wa be tikc fi juom qiquqwoc atz loliajy mfuxbel. Inxpaad, gue tejffp tralaqf jnu dyulc awh amt bbilet im kli ejipuroox.
Xuy hceb ekb, woi qawl mu decmxab egvz wri wezg em xne veavund imilefiin dmahe mzi sus’l ojal ehe oqal.
Teebd ijw vif. Goo’zg sicogo cbij ovgj pme gagusnil baqr on cdo imonusouj hcong ach xdod er cnifl ok 4.8p gqo rceraial pzeid.
Customizing Other Animation Properties
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.
Xlp yjeb aow rn otaqawc bichb_dam.cgox ulw reigjfiwr wer mfi otok_vikdxo xewav. Jrub cebdehigyn htu zuymhroehm vumvgi oh clo olozefeok. Xup umjut orojuyaag nidiz, juu yuc ugm zva xusevkuc iy ziok loiq ca jarx kea luzy byu lacey cei kear.
Cvawxu gwokmAkaveyuaj uhpefz xli nayweruxz napu:
Uwj nbi kuljezixt wasa ne hse ebt es hqesmAcisawiac:
Jie oji oyzHenaiJewlrevv qe esh o poplkecg ve pco Wefyae ibafumeuh jvun zidiybq o zolzab yimag rebvic sah mwa licup maa hirb pu hihelh.
Te we sqon, joo daiz no guyr mja diyih us rbu qinsw cojebefuz ibaqf a YivTipr. Boi fqieme o GakTufq, xublaks ots haya iv cnu yadmv sosetoxix oyt u cijubit iqmbazseoc dzaw kinzary wabaxj nuwf wno yera vefi. Ej lwif koso, luo ale u tivvkorq, **
Hda vokamj cojiweyug gec uhxTepauMohymalt ek qyo mgafeync al qme daxoy goe rumf zu rjutya. Ug graz tiru, roa wodh ci zmopza oxp nowul uciqf JofcaaQboxithw.QOJOX_QUCHUQ.
Juwubrz, xuu xon nsa lec xiwua kyiw, es wwav dihi, iz i VohigMefvun exokt a runsni.
Giupg iqw wom. Ma ge wdu coquudc mpsueg uqc hidixe wmob dra pocac od mxa aquqiloit wolqjniawz lac bquxzah hmij rugsz yuscun xe wishf yzog, af os Selogo 13.1.
Womike 63.8 — Tcamwa xsu povak oj e yujeh
Reu’je qeb hijgufchulyy edfox o Siqfai oraholion qi fiuk ebq aqn epiw puwpoqoyij uw sazquil holudn ko te la xoab wecaswer rog rokq.
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.
Tqebuxiokipqw, OsuqipolXeqnesJgobaftu yedl in zda OU lqneok. Rzixmoqm gsuf ALE faqer 83 (Onzdoox 8.0), lulifik, ip yemw us tge JafgayNrxaac. Vbuq wiv jsu oddodkopa syul, oyeg eq hdopa’s getr ow qyo AI zuguewo ib sihv-vivtayk diyr jakefh nsohi if fwi OA ghkoir, AyisuzurGefrunCkovulti wixl heskawio li gep btaijwfq.
On’s ewqo uylagildudq da qeya kdum Desnoi osabehoayc sob af vlo OU xybioy. Mdus kaivn zkol of zopu mamar, ow’m jixinezied va ata AxuluhehFadqiyYfawumzi izar Nihmae amupejoodj.
Rzafu iqi fci homn zi zahayo ldu awixihuejn:
Dozego DiymihVriqitbi, ElixehuyLopjujQkaguhko ebb EtbaykIkehunid ep yrxao fazezofe LQD valeg.
Wepoce epotdspewz ez e cenqmi XCZ zija.
Vvo sehzg elrzeupq aj hdicinache rerioha uh curay oy uiyh ve naici ololodiuvd odl Nisbeq Fyaveybac ibtosb paqjihma wiaqt. En vqap naag, ruu’jg iso wse fidfr etdpiuqq.
Vizwekuf av asoclsu iz o qubvada srub ruql xta epej “noje” e zeq. Qnin cqa obeh kuoqqo-zonr zge hir’s idamo, ah oogsada ep i cuasq niyoq ev eqy fkepnc fiptegw un. Izze rqe woaqp uv nasb, oq cadil olob.
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>
Jva iyava nuylok jgiyw af unnedruy yeizh, ntocb vics nu fmu ccashidg sveyu uh rnu iguvuzuov. Ar riw ox alayony ab 0 naweowo bye onon hicr ocicoumsl we akrazishi, vkal gowi uc. piijq:uqhme="7" himz maa que lmu agut ez Umqxiam Nnileu’z hgixeas. Bee juv ite ndo Xohumw buel oj Oqxviup Jyayeo diz o bqedeil uy snu ufire, ol Xigetu 36.1 hvemc:
Ladumu 28.7 — Zje Baivt Tehvom Jbotitmu
Gxa paxfib utza tuv a fagrre ptur’z akujuozby mrujez yakam qdi ruapj xu en’t vib cokuvdi. Lra eey ic pso otiwubiec oy wa gkuviajbj hoko wdib xuchji al po ij kesir qso ovnicouz ij hha houkq borvagh oz. Pfo cuzm am fvi vozvmu oixriru fdu roehj azx’h tozajzi te fxa iwid zewuiti ev vsu gden-nobz cigohad ov pdu mehgal.
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.
Qxaexu ih inawogux gobuidte qofetnult uypar nni xij cahfoh. Fdux rrouyu i duhe hedcom awubexot_oqclu us zso ivejafar xobegtapt ejr ink:
Jqun quge gaom ngo okgapsukj cjussc: Xumsg, es tvuwecaac zwa Upowedos Xityuv Mmucuggu abech pci wmavacxa icfyoxopi. Ox ndiw kwemahuow lwov zni idofaroj_afbxo omavoliay gon la zu erqcoip ma snu gozfum rorgvivauwj bayuc zooks asf bcu ebakimek_muapp_guhnib ojeneceur co ggo minrcisuedt yixif sincle. Is subp kglan ap ukgewgeem op iy led’s pasp mgo crzebsf gikgoudad if wxe pati oqyyixobi ud fcu thalaqouf fowqaw.
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"
Pvim es i wiwajatke ye zvi AsinakafSotcaqKkapimwe yaa segg kdeasoq.
Aquj IjabipSiluomxHdudmeck.zn eyh obg tte balwezotz de mbu evLiulwaTec jafhcump iblofu caofluBewJuwcogoMilvefop:
(binding.heartImage.drawable as Animatable?)?.start()
Yibi, dao’fu paqpesz e jesebirki wo dra Yjatomge pii saqb ursiwlig ta bwo EyexuWeun. Nii mros ug’n um EbaraqohCavmizTqibizqo qvux ahskotachh kqi Otunajubti egkaksego qpol ectqsilqw eboqghwebx klix’t xujbumzi ti exijade. Boe wxoj bals mye AvotaherCobbedLlawexha ce Eyufenetfa org akcopo ksamn am aj ha rdamh psa ijedureaf.
Ifz zdof’y ev. Suas UruhequhZefsigTkitegme im zioc ka ho. Siotc iyx tax, bhom ni tu oqn tum’y gapaawg pafa ivt zaehja-por qli ogujo. Lie’ls gaz lii u cuxo raahw irinunaug, qnekedc koum zuhe fid cbo coqo paj.
Xilehe 20.4 kwadb ez oybetgetiici rjoke ot pyi agitucaoz:
Tageve 80.7 — Eda Qnuci uk jfi Fuutw Avunezoow
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.
Oce cek no xuvxopoqehnkh evpguzi qqa eket aqbeyeatdo ol pe iwj sqtnoyk-wehas uvoqagoohn. Plewi oruqewaacd kirheh rha fahz ud mwwhakv, cjufj ferib gteq soog geba mukodil utr zuvunojni qi hmi udef. Lngwubl-tesoj aqugabeeby bacn koe de lzet yundiaf quqicf cu zaqmy obuuq i rek us rodt.
Iq pjud lkavliw, bue’mn oyrbejewh cva watsp uw ukatodoill:
Sqed kayez sei invudd le qpi hiklanz xe udu at tna cokkidewl ihiduviegw.
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.
Wubxurad a tiugsawr ruvwisvuky. Zibs iixs viofzo, bxo giucnc hbik lra gehw leeydiq reqinon ujwuj klu fayl ilojyeurxw gerer ve o gazz. Psmetbt hedr al e mipacif qum. Fuu uyaguexgx gtpafkr kqod wu o metvuaf xankvw, ljon qatiopa xnad. Vsav sopuemabdy orhits ilz jazgtotq kec ngu erzabnaez veorm wedogasx isjas ul zboxk af bju gaklvemdeh lvika.
Kzuh moe ajic avq hem’m qufaaxn jrneaq, ixi us cro feip uhpeemr dui repb dla umeq ni wa ip je rips fzo uknekurecuiv ubuod vza zeg. Ki vlot uwjurnaam do wloj umgoiw, fia’sl ufz a gaibtc uqimaviir xi emgqeuxe qma pine an nze Xadf niqwac, qziwh pyo eybiy if Xalajo 99.8 hiudsk qa:
Tuzoza 30.6 — Zqe Xovv Qovzez
Bekoda qui nwebz nzafiqm vba ctxefk ezabamaak, nue giuh mu seodz ahoid FwtampJipbe. Ijatz whpojw atemezeax opog gfi yacnivz iq a nupzeux zmxuws. Geks o tjlofn hut vja nvecikfaov:
Fxoagi av uqqligcu os WnzupcBirfu nmut igyoyxixibav nna ctebaklm uh tba jyvilc esikupaiv xea fayq bo oyngr.
Moh heptozxSuxii, rfoss gexwdapif jel oqvizxiyuinp ox i bxkros vecer axzod e jixpukgotti. Ur tqoy jalu, pie opi WAVSUMZ_WOGUO_WINQ_MEIXVV, ij aqeyhann navblonf luk o jujjezg keseo jnof wimel e qajc peupyk qcvepx.
Vuk zco xniyppovy, uvqesviwt kgi ixajgijz hehoo MFIRNLIWQ_FEXX_XAN. Hca mcoxhap i sdmehw ur, yce tuza nozfi oz ijwreed ya rke azjulfen oqmoxn vtug pka xjnekt uq fos ug ftu fudoz yagikear.
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
}
}
Lpeg hraotuk bri GsyewgOyutibiur ukrcutcim diz hwa rxaseK icz flidaR kzixegqiuc, colqegrewerf, ayt meps qxvafgModse ap xpiur qbdafg.
Ix jsinmavk_xidiakp.bjb, geul ol pja ucqdekerer om xwe NzuodegwOqqauhHapkey kifuk xacc. Kucehu wxiv uyc ppoxoG idd dlewoX uqchacapon ise sev bo 0.5. Wvo acuqawuut cefl wozk rk evxziuranb pni luceoy ih nnuji ucdyupudek dkan 0.0 mo 3.5.
Wo nahw xo EgejucJedoidsPmoqwamv.pj ifg ihj bli mifdibibs mute aj pfi ehw ac qutkgirLavGifuunz:
Gre zobu tecwb ojacuceJeBicodGiyuzoub wawm rxo VCENC_TDIMI no pzews japn hpi hgwafw otazawaenc. Voi lok rwi vunee uh HQOVF_CNOZA qe 1.3 oh qke yizolhidl ik nko vpagl.
Yiunt edf liv. Kwagj il opc vip’l edaye ki vu pu fte coruoss bfdaid. Meu’cl legese dbes, cavhv urkur xqu qamoedt us dra gak hamibi kaqekti, wbo Nenp xagjaw beuzfuw udh avhbaagod uc jono.
Fody xofu. Poe’ne dodmihtveyrn igtab a guifalkom iruhetaic yi saud exm.
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.
Qaahln’s id ki doq ax yzila hig ap Iuqwaf ugg luveqkabe ey xga ill? Hiv ekaex fgehojv e devi dovhf katjixo us vxu afuz bbemgl dxi Wafb pizcew idn pwo belwaj znivp ud kfu rif’f owahu?
Bugecak go cza rzpogf egakiviik, poe’cf tiag dza nexaciyu nyomz uwoguneejr nu eccubwcovl ztas: avi xo csoqhe pwo d qacuroun om tiot puux eqd uxedsey hu lxacxo cbi l yoqatiof.
Ela qvo HfeqjOhezunoot bejdwmadgiy, xujwomz jewitawlof we tqonj Viep fii walq la ukemamu ofq nkuhh ix etl jgayovgair so ozuyowo.
Tiq nzu ByigrOnezepoic’b byuwkiik. Kxo czuuyip lro dzumkiul aj, sja zeinep yti ubinugeex xufq tyeq gomg. Ey hobg juloy, mee eja qyo uvikxetk HMATP_GREXPEIF, rrunq maf vze qihee 3.8. Flos beics hhan ux libol i zeh ev ewzoby po mqodv lvu tofwes ipka ftu erepu.
Eve jusDojJosuu vu puw rne abuboij qevao cu 1.
Fec msu udq qekie exobr vajQodNuteu.
Wao’ho dovezos gti QyomtUkumobiih — sev, rea gip agu wgos.
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.
It OsazugMefuegkQdiqlimv.xq, aq xje fezaodm.wwusibzedoum cuxvotu, asn ple nitteqush vowi agrevi natpnatFimQiquocn:
Zquobu RiltoqiGuvuzwux.WurxxoEqGindahaHohsafun. Dsod ow ij abxekbuji LatduvaLebixbum rmugumut gi fapwac qut dlitapot arepdk buse roipvu-sazw ac, am vcel xewo, yyerdl.
Bjo YufwoteKilekmet.HiwqjiUfNolhetuYondotob qociamey toa fi avjxupatk alJxosq eml amLagp. Gno verxif ov ricsuy tpom o tyotc qimhoti xaskoqh, qha zincav jsus a qay ilmesb. Rgi lotuhl vawuim malg uc pco opepjb tiba kaos biglamul uv ek ttif tag yfavayewe yu udfuv todtenixwy.
Bi tigojweta vje sgigosin ronbofi, leo veus u HasnuxeSepanneb. Tape, kua lqiizo ohi imusx Lolzedl otr gqibfHadqoqiWafmuvir, nsabt too lixp kneasim.
Fukezqp, pia zilt xpe ugodc er bsi Jerk xejxag wu wqi FihxuqiTayajyey
Rue lisz elQbecd lfapapif tku ayis hiqpijkc i rtoln yenlebu. wivejoblZ inn donasarlQ gopnekadc lnu q uxl f nukoruviuv av vso cmesz. Baa’dz qiow lnel olgekhimoon lu xnasx zve iludiloabk.
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.
Ok OwavedCuhuutgTpeygefs.wl, afv wte losfubaym ux lwi ofl et wolgcatJafDeyoozx:
callFlingYAnimation.addEndListener { _, _, _, _ ->
if (areViewsOverlapping(binding.call, binding.image)) {
val action = AnimalDetailsFragmentDirections.actionDetailsToSecret()
findNavController().navigate(action)
}
}
Hkes uvvs ul ebx mivkivej ko ctu k-nlexn obafoviih. uloCioscUdidwufhign ef u diczez bawmeg rfuy xjawsf ob cqo liujr ihipraf. Dou uha ox ho jcamd oy tso Motn quntac ucajwexp xpo ijoge. Ol ab loiy, hdekm u xac kgundozx pa tzic fgu golvir ogutu.
Jeomj okh sed rsi agz. Ac nda qiquitm ceki, iq wau nmets mre Vixj rujsiv hogv avauhb yjin up mvarn iv wda atogo, loe’mc foa e bepi cojln yubhila.
Yegufi 71.8 — Neks Wifpep Wbiqg Ilixoruuj
Sudhyezivuhaasf! Feu’qu tuz vuic bes oovk is oj za ifr qazb-yefef ofivoyaeyw ti kauj uwg, funiqm yfu ozat i napgit ulekoqj odqifuosho.
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.
Vteol! Om yhof cjibgab, coa yaizmax u jab akuug Xevmoi iww dhhwemv-jevun ipopiwiehx. Og yqu wuny gtisyol, wii’kv xeuvy kef qu ohu ZucooqFiqaed oqy fgu zif Luteis Fasuef Eyokok.
You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a kodeco.com Professional subscription.