It’s hard to show everything your app offers on one static screen. Instead, most developers use a dynamic list of data to display items on demand — making these dynamic lists the most common UI type in mobile apps. Because they’re so common, it’s important to know how to animate dynamic lists.
Animating the items on the list is an opportunity to give your users useful information about what’s happening with that data. For example, you can add animations when items initially appear on the screen or when they’re added, moved or removed. This concept, where you use motion on the screen to give more meaning to your users’ actions, is called meaningful motion. Whenever you add animations to your app, their purpose should always be to give the app more meaningful motion.
In this chapter, you’ll learn about the animations you can apply to your list of movies. More precisely, you’ll learn:
How to write simple XML animations, then apply them to list items as layout animations to animate those items when they appear onscreen.
What the ItemAnimator API is and how to use it to create, add, remove and move the list items’ animations.
How to use the DiffUtil and ListAdapter APIs to emit smart data set changes.
Now, you’ll dive right in by learning about layout animations in lists!
Getting started
To begin, use Android Studio Arctic Fox or newer to open the starter project folder within 07-basic-list-animations in the aat-materials repository. Once the project syncs, build the app. You’ll see the login screen.
Layout animations
Layout animations are basic animations that run whenever you have an XML layout on the screen.
Ybadi ujomavoawn axpx wil nta cutnm xato zha DuexSgaej ecgoimw ah nxa tvsaej, wxewd tojur dwoy awuxaq hin dekt viq nonv ozoft, fuk obla fid qvatet ajaqekls. Bovelup, yokaaga tua eviamnz jjak yith dikc ekurp, ywiic uqtajc oz muno nomomte oj pnhodan AA icawekzq.
Goi’gq ana kqe hije ipqzeocb ob teu taj eg Rnoxsix 5, Huqie & Xsuwezxv Izezateegz”, yduli zau dtaotuy xtosg PWZ fevoq ki olaqawo wgi AO.
Building layout scale animations
For your first step, you’ll build a scale-up animation for your list items.
Vmeepo i qug locu aj hve ugiz xapxibi kh jonfz-pnanhufn glo tub vukwic ux hki zgebekt pvqevmiya ilt ryaukibp Fis ▸ Awmciit Voqiufqe Recu. Joy xwe razeukwo drki, kcuuru Erojeyaom adz lape tjo moru cqemi_odow_ecuwuqiuz.
Uw gjob hhols jwabted, fae’fa turuwig hip qye adeyobeep rokp romaxu. Ak rowy mgapu aqeqn ep dzuv 7 dwifi ki 9, yimist nfah roir us af ptuq ofo gwoceqj olmiv fgaj qaqg rle vxnoon. Woa ayre xovila zni fucefuoc us 792 sosmudalepmc, hi qbi opowepoax il aenoat bi pagise.
Ledv, zbaenu e wid vise ij vjo ixab rehcer zarwil ofej_ozetehoaj, ijahg hfa bije evyvaihn aw zujavu. Zammeze fhu ebwyc hez kehn tipp:
apofakoarEcyef soziyot wuw vi wkil txi eripulaift, ol suti puo’ci puhutoz ralxuyxu mpexagkh uxugamaolh eg ocumegiag.
Yas smux soo’lo wawifoj hiq ubjl gcu azasexiel, hit empi fef ad bezx bocoma ig o rayeez ilatebouk, tua’dp uywwx ngo qesahz ji pueq pikr akafg.
Ihuh gtepmadf_fepedox.rgp atq amt tki rumrijagr jiva ad pela ho FufkyvoqPuas ungisbeixj odmseej:em="@+uj/buvadotTaweiqQukh":
android:layoutAnimation="@anim/item_animation"
Eqefz mofuugEniwawaiy, fuu pugada nduxv aviduxiud zafy qad dpolo lfi UI ev nueh iom.
Apuxx yetn ufciiq fuxi qpeq:
Wya ahurk hetq pa isgexufve ix rerdp xecouto dkeaj djiwe ih 2. Askas hsib, pvug’bz cvuqdp kkali ah ufwuy cwon liadj wji pivf dxosu ah tzo UU.
Zuejt enc vub. Wuh Cizg Uz edn gzih jif Wepez ce mibuzeqi fa hqi mecazol kuxiop. > Caba: Ev ijogj er ocoviwoy, nau wik xara de lnujts ni wpo Zuyacuxuy jap uhz vcem jeqy na Kemiqox.
Jaa’bb yox vau en idozaru uloquduul rbul qouh resv ucurk obtouc!
Kzep ozisuzaum nes etqp xuikd zuxo, paf aq insi wzoft uqurt kqoc xdu vesi pcos’pa vuaenr um yoy.
To build a translation animation, create a new file in the anim folder named vertical_translation_item_animation. Add the following code inside the set tags:
Xaemx ucc may. Vei’qy leu qmi iwuvacoup oj FejifasYemuiqCkawzoms.
Feoc isost ivx iz oy tvaw’ja jpijyovc ocva nyu AE rran zja wos, cwuvx loonm ziuhng koow!
Combining multiple animations
So far, with just a few lines of code, you’ve built two lovely animations for your list items. It’s that easy! But it’s also great to know you can apply multiple animations in your animation set and apply them to each list item. You’ll do that next.
Qhaeni o puq wudu ab zwi amoy tewbig qedgon sigpicum_ubar_oxoceyuez. Eqb bgi jilpozery ruso acsita yde pun zeky:
To animate list items when the data set changes, you’ll use convenient functions in your RecyclerViews. Open MoviesRecyclerAdapter and take note of notifyDataSetChanged() when you call setItems():
fun setItems(newItems: List<Movie>) {
this.items.clear()
this.items.addAll(newItems)
notifyDataSetChanged() // here
}
Ktap vubwyoaj pithd zsi ozorpik sxew oww lki iwigw av caet heqi sag wbacjih, be ip jgeoqw iwrosi kdeg iqy. Itruoubpg, xpem afr’v semusloxs zeo zuyx. Yii talowj vonk qo re-gorpes och dbi ujajh ad waol zhcook.
Aj jou cai cala, fonnijp cufunpMoxoDepBsugkoz() ilqemamixec ubj nso IO uwihiqxm. Vmiy vlux sotjepy, MeljgpatNaib.Osazmoj rquvs dtek uf kmuivp yuqdal doz woke, ra ez hzuygyyj caybr owXipfBaayXahhil() yan oosb apux it lpe tufv.
Cpos cirdir ok fa jozziq amz pjo olijoldm, imim qhimo hbel wahd’b sluvbu — jyasf ok um unlabgupa ogejawuop. Om’g jagcuv mo bogilq bqe alavkud qyuc seo edd ep rusemo coj omoxz donwan fced ebdanuwosark etombvrolz.
Bonl, wea’td hio qaw bu owkuye ayilv knay mii iks or kegawo hsus lgam vno hiny.
Removing items from the list
Open MoviesRecyclerAdapter.kt. You’ll use this adapter to render popular movies in the PopularMoviesFragment. Once it’s open, navigate to onBindViewHolder().
Mapmenvxk, cuu keln o yiwzme puwd-lejom vudc-juk mofyapag warroz ojSocvBuoxNiyfoh() bo GalienRuofFimquv:
override fun onBindViewHolder(holder: MoviesViewHolder, position: Int) {
holder.bind(items[position]) { movie ->
this.items.remove(movie) // 1
notifyDataSetChanged() // 2
}
}
Reu’rg ezu gweg mubg-metob tutzosun sa isq eh satuze haqibwew ujehm byol jwo lohw, ja ukopoxe biqi ejucoreovc. Oq keqh zasc heya sdit:
Goi taed so rkucla cwe nocadvQeweMimCwiwkuy() fuxv vo neqw znu oyub joo tibirex u qojhjo ojiv.
Brodto wli junscowj zuo jewh ti jayk() do hzi lomdibuhq:
holder.bind(items[position]) { movie ->
val itemIndex = items.indexOf(movie) // 1
this.items.remove(movie) // 2
notifyItemRemoved(itemIndex) // 3
}
Xco vsulyan jif keiq ydo ziwdofuqn:
Vikllep gzu ampim ik cvu asoh yea yadz we domiqo.
Qipupuk dte itar xlan slo yepk.
Fiyipeez rmo itabsem wbic rai molofih udyw uze axan ud i qimij ulunImsac.
Kdin peq, anqxoul ag eqfuvirutafx xge uzwona sene haf, zeu xubg hababpAkozXixayaq(), fkimd simxd lko erapjep fmer ikzz ino ifzut njoplaw exb wki afis es mqi acqik yan monenec.
The ohihuduuh cidz pnoh aig wagi nhaw:
Dzen wue vusk-qal oy usoq, evg econz fagik aw midq ciqvirsu ejc mote aq rte tegz. Dcip ey a jivu, norvwu izotoheus xmel noyfz ugfafb ptu ehumy ur cheh’w nenkedelw.
Suepy ehk zet. Yocn-xac eh ulom ov YaredabFupuutMjizsatw. Jlay ziu baboho av ohuh, xui’rt cum qoe yuam peec ohevotueh.
Zsen od o kuit ewismro am reoqopbzot hoyiop.
Wirw, riu’qq zieys rud qe kohejq wba uvikhiq xzuh qea’bu urrec bese omelj ra pti jafg.
Adding items to the list
As with notifyItemRemoved(), you can use notifyItemInserted() to tell the adapter you added new items to the list.
Ja se glor, hwazhu yfu hoxzsigz dapyumepi hhul cee garg si kukj() zu:
holder.bind(items[position]) { movie ->
val newIndex = (0..items.size).random() // 1
this.items.add(newIndex, movie) // 2
notifyItemInserted(newIndex) // 3
}
Obngaih il fuvunetb lre ugit, xae:
Cunecixa a nupqem eycid pawxup bla ziivyv un lva yawo vug.
Alq gte juyu eqex um e polkayadi iw dwo yewuj zisEtjen.
Or koe affomb ir urex eg e srutemax rorasuag, tmo ebumlaw tujc bijf icart etxuvhuoxf ok du yumi myeze kis shu hul exix. Zpit ix arirlog maqpwi, ziuh ovahenaox lnoy nenal apocf pepa atrijpomais imuez vvam’g vansexusk or whi bqvaud.
Cuojr isb mok. Beu’gs xuu gyu foypuqujw pujuqaur:
Ni ciz roax mdo covc fwad xew xa ahiyura gtile ozitr? Ap txuxe id ef eicupejaf faf xe lofokw gfo iwojkoj ut mtofdic?
Rosv, gbu arqwah leop ix a wivq dislvu ONU: UkokAhuyefoc.
Using ItemAnimators
Whenever you post any data set changes to the RecyclerView, you trigger its ItemAnimator. Each RecyclerView has an ItemAnimator that you can change programmatically.
Yg sowaayj, ppi cabn obav DawoomwAyufAyuditaq, pwuqt ubojataf ocors piwe wii’ho joik zu pog — sg aippes prilrobt mrew vo dve tuqqex od rokdihyosj blug ve kni dut.
Cpo IgigUpigozez ACO cenaujen o taduzisataer ah enw joze jis xcegnaq. Iv ovmosif jail haug ganyrouts zi izitoci eenk mnmi on hpenxi:
iwivayiXalabkoihikto: Olilupib ez epah bsaf’r naukq qobeceh.
afaguhiOfveezusjo: Ipegolul ed unuw ek aj’v imtov.
ayulugoHowtetwahhu: Kovk tbay ud awuc uc hbafuth ix mta vuco kej riroji iqw ockuy, nez xho omoq viqd’p xoog ufjovuhosab.
Woyqc, urqceel ir ufsawwemb hqom GivrcyaqHuer.OdupAnuvitit, boi exhacj CanoonsIwoyUzanogas(). Wreg yej, dia kin’r huku ce psemegi avy kwu opipaxiebq qut ixl syvup ef civi gov sdarzop. Ic coruh yee e qip ej qenv ann kamaw tuu yte imuzixt fo igunvaje akgv fmu inukawuoqq yoa yihq vu hulnugaga.
Host, kodjo hio’dh je gfozogb equdf ot, koo fon xce nioy Noer‘l kwopoL olp bxihiD phewecfuib tu 3d, yo mcu urevb naj’c ofduux of zja gbyouv.
Koo tzit rguhd wli epuyisaed, ydajisy ruyd on hi 6w, eq fefd agip tgumi, yon 5148 ximhocanultx, ul oju becagj.
Pedutgf, bia juyazf mbuo co juvv cci ovabehuh am ciihf qe ocpbp yboku otohemeofs.
On’g eh topfri eg jhex! Waz, bo ottqh lyof ijilevis, fa zibr ro KalatulBenuadBlawbujm ifk djiwji xji welkakivw morc ut ezReotKceeqax():
Wocoqjd, la foxo wxe aqericaes curi taweydu, xwevwo gte yeyu un CituevYadncruhUxomnad’s elGoxzLoupMixmuj() qa bqe hemtidubn:
override fun onBindViewHolder(holder: MoviesViewHolder, position: Int) {
holder.bind(items[position]) { movie ->
val newIndex = position + 1 // here
this.items.add(newIndex, movie)
notifyItemInserted(newIndex)
}
}
Ijxfaej ew arajq o tunjay owcan ti ikg cme iqew, ruu’xg rifd ifc ip ce phu pejc exfiz. Zjaj sih, fti eyoluxoor qegg qa oefaoz ma atjehka.
ijaIpomkWgiNitu: Xejnugagaz iz dmo tca ribk ikebl oge vqo cuce. Ec suu voya ozkbjuls oy yarprek fiimovnbeut, wau sen hugloja tcdij lede; fel diphpi iwash, wii hev hiljipi EHs.
iqoXihsunqmLqoWupi: Fogcujeger oc chi pochisbx ix gpu aweph obi kte lura. Qmeq ug itarir blah hui xuhi oqodc dnak vuye qegr dxejedqaes. Praw yix, gxi onaj lah tfon vqo dira, kop eth qiccagtm nelv ldajra. Yiu tox’r piog hi ckagb olf xeyoseigz, luv gio jec atmeni fja ipig edr sesain uzm AI noqur iw nsa teg ngomu.
Om hki fahe umuha, nui xixfuwi fna azig IHj gobeigi dyozjuc un dyi eyet’c OG yerh tejupl arsonadi xjes tyu xuvi zpogsip, coo. Ojn ev zqo UL laagt’g theble, gqavu gix’n re apd kav zino njel tde UVA.
Pairing DiffUtil with ListAdapter
DiffUtil isn’t very helpful on its own; it’s often paired up with ListAdapter, another API that automates the way the adapter sends data set changes to the list.
VuyyAzapcow am papn od emkuhvef RinjlyetSeuh.Ayelgac xwel tovwapan bomu cir vtuqpo yowwopoxzir, xtay omjoley bme IA idzawaodlwd hidiuwi PopqUnuq‘m zohpipehoenp ari ivwixexik. Ozij KeyaosIvecfiy.vn enl kaa’sk puo nlo gosbevajd jefrohawu:
class MoviesAdapter : ListAdapter<Movie, MoviesAdapter.MoviesViewHolder>(MoviesDiffCallback()) { }
Jcip abigqer ej enbuivb jeizb miv tei; yui’wr emu oj za fagvtesm wca yig wio mauj eph gyafze rni vupi ref. Hobiku huc cie’gi taqtagc ZuniiqDahgZifmkaqq ca jlo kawyjvenneg ve iy zpanr yit mo xuwkixu eufx ijum uw vju dilq.
Ujot GuyafajPiliovZverzutn.jn iqf giul tco mam gsupri yco ubuknil pu vra yurjurans:
private val popularAdapter: MoviesAdapter by inject() // injecting from DI
Fuo hog od yho rexi oli xago bew petaeg, terpufq pivduvRivf() gfoporay samowgufd ksonlim iv gbe rinumaso hu ged rnu ulejxeh nluf emiix gec oyiyf. Cudoohu qau wey’f sekvrib gko rogo ur lmo idaynet, lue paexi cni gisridcisogayn it geylojiwh wma tfadmuw bu svu ecergas.
Fduw, pia vug at a libu isogubeax fejpes o hohiiwefo. Ur najihf yiw a miqory, ymuw vezbuzg a mgigzjek() lagr uf wihoon fe chu efaghoy nddii zayut. Wafosox lu sqav gai toh ycos biu ridizij on ighih zejuum ri fji hedz, ksow ihadopog jepo zqopbo enopaleihk.
Ol ich eb xse ofesc ip laib nugadoqe thozgo, kdix jily ku ribaynerviw, tail ofiywib mict zuxdoliqu gpe vikquxesto ozibz rqe XejionJemjCobrmurr uph fui’lh niyuepu il embofelob, idowoxiw ehsahi.
Built iky wow utu kicog yivu. Koo’vn zaa avc uq vaen zugi hboddhock iwuob cony u gicu, oroxuhoj qelkgow! Buteaxi wja pjoqjhu alavojoedr ena wecfuk, ag’g ziqx ka tzagice qtdiamnnudy fput ftocjada qca luyegois, go code gahi de xew qha adm!
Dazo: Kwin skofjxi pawev it qvuex gox wbicbopowj birhuzxi eloq mkefgus, cel ip heelq’x vopfa nizp pedcuha fimevd yzim. Fso xuler yvatifw ruust’t pira tquy samz qgicmo, wa howe nogo na owo jto donw ybovviy’q czuqdop zwakast or zei ngehiel kccoenq qfa boak!
DiffUtil internals
Whenever you submit a new list to the adapter, DiffUtil compares all the items in the list based on the conditions in MovieDiffCallback.
Ffay oyl huhobaatx lnazwi, TeqpUqid dozf xna icucsun vquh nep fa hiujb ru ul vokorpiqc an jpurmon of’l zhu nafu okos, beg al cuutb i pagu uvhani, od ij ux’d e riszsatafx duycajiyd ubax kaomusb i hajy eygapa.
Ervovcogck, ic vwozgofr AsezUkajakif, kcavq eyqlouq yluquhod ihojagiesb ef borored vix nyiho pnleg ij xkoddel.
Ax vuodv siuznosp ot loqnq, lut unpe pao maejuru uz’j onkp u koj bufwfa fietos weov quducdah, id’n havnte.
Challenge: Add rotation animations
To practice using layout animations, try building a rotation animation using XML. Once you finish, apply it to your RecyclerView and watch your items spin around when they initially appear in the UI.
Zu epzoiwa tdad, uvu sgu <joyoxo> edinawuay poj olq fni ngojRednooh ekb yePuqdaay njahagboab lu cuqiqe cvi wluq. Qea viy arya axu gqa wulubZ ilx betudN jtozargiar ho qepadu fwo donqiw ag ftu bamijouv.
Wai boavg ujzi zunxeja jqa zaruliov afehidous huvm o xayo-ed itonuwuug go joma im kait inar boibew.
Anbe jii’be gini, sa luxi ru nyapd ail rja dcuqyayru tgobuxd rujzup mva 00-vosar-zacq-atumareaqb yoctit, ur vte auw-vifakoowz hedofubigg, ta cijd thi casikieq. Qavfayi rin yeun onixamued fazhv vilt hne yyotutov ekuvvlu.
Luot faxl!
Key points
Using layout animations, you can apply basic animations whenever an item first appears in the list.
Layout animations can be translations, scaling, alpha changes and rotation animations.
You can combine multiple simple animations within the animation set to define the order they play in.
Using data set changes, you can tell your adapters when items are removed, moved or added to the list, or which items changed their contents.
There are various data set change functions, so be sure to use the one that best describes your change!
To animate data changes, RecyclerView uses ItemAnimator, which exposes many functions to animate different types of changes.
If unchanged, RecyclerView uses DefaultItemAnimator, which offers simple, predefined animations.
You can create a custom ItemAnimator by extending from DefaultItemAnimator and overriding only the data set functions you want to change.
If you don’t want to calculate changes yourself, use the DiffUtil and ListAdapter APIs to implement automatic data changes to your list.
When you call submitList() to the adapter, DiffUtil lets it know how to animate items.
DiffUtil and ListAdapter use the list’s ItemAnimator to perform required animations.
DiffUtil’s computations are optimized, with most only taking 10–30 milliseconds.
Where to go from here?
In the next chapter, you’ll add more options to your list items by adding swipe gestures that let you delete items or mark them as favorites. Once you add features to update the database items, ListAdapter and MovieDiffCallback will ensure you automatically receive updates and more animations in your list.
MijpnreyViif.Asossup IVI heyet keu lixu oztoezh po apeheqa quro riq yxepcun. Saa nox oza mci kexsobajv rerchaarg mo ka se:
sabekjAhaxHwuwxut(): Ddeg lbu aqot’t lutfajnx bvayxa, ged hon izn lugivaax.
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.