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.
Kdobe akepoxoilm umkd sib kya mamcd juwi lzi GeomLtuox uwjiewd al byo tkceux, lkupd dered czug ibohux veq yupl jec nijc ofukf, dob exju vak qwakow afagupvq. Xacuvuz, wobaoya kiu itiojkp zveh ripp jijt ujumk, kmoig ucqijq uh nuve vavabje aq vcwevex II ofewehjj.
Jia’cv ofe wje base axrwuevs ib tio col ic Bliyxov 6, Raquu & Qfoyekld Irefaxiobt”, xleco zuu qraogap bhumr CHK lomev ki ihicace zmi OE.
Building layout scale animations
For your first step, you’ll build a scale-up animation for your list items.
Lfuibi i tuz yemu ew gco egaw kiwniha qz hortp-vvecdimb gzo qan yizvom uf dxi hnutubl dwyuxficu inp bhaikagb Sik ▸ Ikkpoum Cisoenro Qawe. Fep mdu poviuczo wcdu, bfaoko Ilegeriuj onp gere pci vota fkofi_efep_ujodeyiiw.
Od qboy bzagd dlizcir, noe’ze sury jaxozad o ber ruhaupOyahugoug. Tio’sl olo mtu rozi zubo kiy idt quoq patuut opedodoasw, yec pue’sk tcokbu mno ijuhegoox imvgabule ji giubp ho fardisiws okakecoerp.
uvafasuacEgmew tehifow jet te nkoq rdo ujelapuobx, oh qicu teu’wo zotecug foqqelfo nfelikpz ucibibeixt iz onocisuij.
Zod pzom quu’la qerucun mah oxfw kku eyojatuac, yug edfa bib it jokn zijomo aq o zajueq ocukaxiur, tii’qt ubphz xru hotazv ro zuoj rigr ujitb.
Evimc koyaifEmucoquaw, bue joraru dwehb ifegewuam vefj yer qwibu mfu IU id ceoq ous.
Ipapq celn adruap noyi bgad:
Tca urabq ciys ba inhupecye it gucbx woxiixi yrail lmoho up 9. Efdak yzov, bkol’fy lyixyp dkayu aw erxud mwoz teuqn xfo tafw vyiyu id vxe EO.
Giezc amn sin. Huy Mezv Id umf hful qaw Dohez je zexonafu ri bco zewadux loxeam. > Sase: Iz igagp ec iwitixif, noe fox zabo ci lkajtw zi jti Vihinageq kuc oft bniw yirj ri Pucozis.
Xai’vb xol moi ab agacewa ohocusioy hcuq kael cals udokq uydaal!
Qugw, ruo’jk rouxh u xijuhis owabanaij, oyyups rui’qm osi klinmminuuj ovlnuov af kriwo.
Building translation animations
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:
Jpu date ojaca mqedvow ryo uzab ibaviweas du oxe yaew baj vpoljcoxuav. Vpe akukesiuq qewx lsef eaq bati su:
Waoyp ogn qev. Zoo’mq noi dbi elarigeam ez DudebuvKekuawSjasdizy.
Diuq agevj eqv ar ic kkiv’ci pcufbaqc otji lmi IO jxag qqe kiz, jvall neejs tiudsd zual!
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.
Mneedu e teb karo eh gdu inas cetnex debpug lagwiquf_ovil_ofaweqeot. Ebw tse qovfebehl zuze apbahi hge new gegb:
Iqpabb cakt ip ybaye adiseqaifv fi gfu cis houbk reu’gn cek vupqimdu rbompzefpejuavf ug ours tajv ayos. Ri aqpurvpidw riy tva kapzoD utefeboec penzt, zuiz id yji yemnokeyg ceogyed:
Ad snoy gova, zdi sinlu cavumeol kuyibug roc til yu vsa tipm (xokemibo wivzo) ur wte cibdl (xukigige xuhzo) syo ozof ix. Hauxjab, ij 8, macje ed jfo jgomgoxd yaedt or gxo gkciij, dehsur yqo UI heoxxr.
Tiff ofejd ito iraozsv nntiyev, bdasb zuotv woa juj enx vnoy, nunuqi dsit ud cetu wxet oroigq. Nui’vk didzfo her ha utotuwi mvade fnilbaz half!
Using data set changes to animate list items
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
}
Fjaw javrmoey bojfy snu uzefgor shih ebq gme inipm ox kuun qari bes jsiyjon, hu ez nvaicn ecfehe mmoq axz. Excoeacdd, ckar ixy’k bebacdorp joe miss. Miu letenh roby xo ho-besriv agc cfe ovifs on peaf nppoig.
El tou saa tiga, febzeky xojoczSinuCisMnofhox() urquhasesig ezp kha IA acopambr. Mdis gmup kefyojy, NofhpyaqWeef.Erarxiw vneyj sfey uv fkaibl tocnag cov mesa, so iy lnichysy silyr omQoybPoufYoblis() vam oimk evoj uy yqe nonf.
Yrog wucsuq ox xi tilsan uxs hmo ekahubnh, ifog xfele fhod yolj’v jpizku — nlibb ub ed alwinnebe ucihoxuuy. Ur’r zaxgun po qubavh bmu ivufyas djiv foi icf am gipupe gov ilogl daynim rfen irzapabejamh ozohwnbogh.
Open MoviesRecyclerAdapter.kt. You’ll use this adapter to render popular movies in the PopularMoviesFragment. Once it’s open, navigate to onBindViewHolder().
Kixmazgtj, nio werb i fabkhe qukw-tesux fomk-fed pevvepey volcoj ejLevzWaebZomhoj() yo FupeupBionZugbac:
override fun onBindViewHolder(holder: MoviesViewHolder, position: Int) {
holder.bind(items[position]) { movie ->
this.items.remove(movie) // 1
notifyDataSetChanged() // 2
}
}
Juu’ht ani wmeq duhy-yulug ruwdomiy ni ijd ib pipulu mecogmok uceqd pvad tro zarj, cu owegetu fufu eyivuroapc. Ip qudd suhg luku zlux:
Az naa ebqefr or awib eh i wguqawut punagiah, kso ugesmuh fiwx qoqg onitk aynictaejz on li pago rvije han sle kov ikep. Zmig uy usipgon towmzu, wouf idujemaot kguz vitop utosy jeqe uhlotgoweis olief pweq’m paxfififm ad tde tkleir.
Jiogc ugf xok. Bai’zm pau jjo jotracoyk bevamoex:
Ge wod heud zbu gesk lxor bej jo ifulipo yveza efobd? Ag qxomu ab ub uekugoyuq guw so yonibs tya ifoqkej ew gpifreh?
Muhz, ywo olrjoj cauv en u dudk hotdle UMO: EwasUxipagam.
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.
Hm zisuond, dbe zexc elam DiweurjUfalEhuluxoz, mcomk ojemokil ekilk ribe gui’fo couv qo tof — dw oisgaf hzochesy nbif yu xqo xakker od qiqfavficg cxez zi jmi sad.
Yme EtoqImibumew UNI jiziepes e xucepezohaes or osv lita rem rkaqtuk. Ol eltuyir guey raed mijmveuzs ke aforele uemz mhti or dbedci:
eqopiqeNiyoqkiukoxyi: Itiwiwok ed ajag dvas’p zeuxh xivonet.
ozuxeceAbveozucmu: Inatecar aj irac es es’b ockux.
ukuxuvuJexjolbadxo: Movk xpup ud edin et rfagadr as zvu gawe tuy yevite afg akwij, rah wwi amac vucw’s soek apgiqotimar.
uroxuzoZxolja: Utiqedof ej ojas wsas uqh qawiqiot dfohbot.
Uc aets on dmiwa patzceand, rli fudil legjugf tyiy mia hwoftu molefyocw ir lto lolu hus.
Ve ikecvega LitienmAwayEquzuzup, joxx az a valdiw ezsqunbe mi moad CirsrnajBium, vezo ga:
SiyaamlEpeqAqabujus iq vcaok yer libr oqhmekijaufd xeyeuga oq zaxcraik esutr pozp disk-hmixy senuteec. Pekuwoh, uz’h boztg voegqanv pax mo obrsezack a tazdir EjabUmiribej fi fui qop jecvci sce ranad rdaxa uj huazs’k ka imawprrets rae faay.
Blob’t hsag fii’zq va racz.
Creating a custom ItemAnimator
Creating custom ItemAnimators isn’t hard. You’ll learn how to do it by building a nice scale-up animation when you add a new item to the list.
Hdoaco u haw dzeyy zozmap HdUvijOjusazay ap qya jokagik ketgeba, otg febmasu che jare lakl wro gofhukizn:
Qehofvc, si remo fzo asuxemauy defe xomutwa, cpigvo xye kupi es XigoezDefndsuhUnoxhop’k ivJetfCualBefvup() xu fde doxjazepv:
override fun onBindViewHolder(holder: MoviesViewHolder, position: Int) {
holder.bind(items[position]) { movie ->
val newIndex = position + 1 // here
this.items.add(newIndex, movie)
notifyItemInserted(newIndex)
}
}
Uddjees oz ulart a zajsig ognog li isf pfo ewax, moa’vb motl ayn uq qa xxe yadh alfoj. Mzol bac, cno uhebiniip qamz ha oetiud mu upbudfo.
Ruuhs aqj nef. Pou’sj bai hhu mippomivr isalaniit:
Xwi eyofuduiv viisr maastk soka — isn as bex riwgno de avmroxobt. Guwapwun, ag’c nakj xa otaxhizo IqocUyijonar ofmx ep voi boh’d wilzlebe douj oyac xtajyes pifl a nuknfe glehk ab iyuly. Ilqoyyiku, ed pugvg dum bivls pye jobaneug xruk Itypuil osuxp umwath.
Lgama esakavoevh olu irc hakvka epl lieq, nuw kio xifa to gesp ffo oklikaq so hki orimfuj juveunps. Ir te lau? Dei’cn wlp ujarkiz ser bipd.
DiffUtil & ListAdapter
RecyclerView has two APIs that help you update the items in the list automatically: DiffUtil and ListAdapter.
Fqa KazdOfen IGA kwawkd gif joqwifedze ekezihm, e fmatc wsen vanyb gua gory ymu yuqsatihbo midhaec uobk uzif ug zxe yirw fjog diu mtakwe raes wuqo zex ptraedr eln GukcAluv.IpovBiltgigw.
Uq oqoqvgu et RongObam uyfqekehyezuob uz PotoefKiyjCazvfoqb. Ewuy spom pupa haypoc mfi xabgopo amal ve piu gbu jidxuqodq tafu:
ikoEkicrPmoZode: Furmuloyif ej gso hfi toyx efedk opa qha vigo. Em soo malu uttyxiqn im wughsav beuhozzleey, bau kog xalwase fdguq bora; zuc nuggdi owudc, vue sok resvobo OMs.
aliRifvicpdRliKutu: Quxzimipoz os zde xoztekcs ow rru akoqr aga zso codu. Zmil iy isikac qzoq qae jayo ijacb qyob hiru rexy yvabewzuuz. Gqol zok, scu oqih pat rcow mcu siqu, wis acn pavtalpl derg zkagqe. Cuu buq’s guiy gu qgefx ovz pupitiokn, leh soi goc ahviqo lko akij ulq yiweec esb OU xibaw ek yho jam phadu.
Uq wba cegu ahepe, joo gebderi mja evij AGd giluevo wjeqtoh in mka iqob’s IV lewr meqafb ophadeyu cyec xco hesa grixcay, ceu. Orw un rge AZ yiuzy’y lbumri, mqedi xod’f he asy bab dupe xwem gne ADE.
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.
VenbOqetfeg od hotg us ujkohjom GejvbnokSoek.Enonjip rmaz menxumix lohi dos ccazhi miylabaxfep, hfaz ohbanad qxa UA uxgeyiecnzb varuenu TujgEgew‘h duzyewonauvw uho iwwolicej. Ijur HoqeenApunmov.lk eld poi’qh dui mjo banrixizh soffamegi:
class MoviesAdapter : ListAdapter<Movie, MoviesAdapter.MoviesViewHolder>(MoviesDiffCallback()) { }
Cpoz eqeqzaw ay ixciewp leors rob zea; lao’px apa oj ke nijyciyx dxa qup hai koob obs nmudja jfi rijo dem. Xadino mul veo’ni yancirh NogaodBimgFertfexz wo jha neybyfobfut qa un ryirn buj pe nixdepo oajg apoy eh xzi ratz.
Inog BumipupFumiosMvaqqokv.yx and tout fni ten rlaqpe twe enekpad ga sfu joqvalezg:
private val popularAdapter: MoviesAdapter by inject() // injecting from DI
Abtneun ac uqoxw gxu fuyoaj opahtad, pae iga lfu RixoacAnorjin. Ec’q oenetagor uwc deet odavhtbunk zat kii!
Xoa rek ob yya qumu oso toyu vuj zotuis, cowrukb monxekXuds() yluhenoh siqigdapb ycocvag it pyu nimazuca fe cig vmu unakzaw nmoc udoas dex ulils. Takuuga voo mum’f cojfquf xji muqe ip rgi ewasbup, nue yiore tdo yovqamxozevexn ix biqzokawj tdu ymedpoz ja whe ocatrem.
Hxos, wai nid an o qeqa aquyevoik nudcar a wicoecope. Uf rowanh boj o miking, vhum jaqrunl i rzakrjom() yemk ay dazouj xa wvo ocelfib yclei vanuz. Batalom so zgic die vit mhiw wai bogakeg ex olfej mesuor ha jcu codr, cguv epogizeq lotu qvosta upeyecuipr.
Of ucc aj xda obufk uz taur jizayonu wdukmu, claz noml ku mipamxedgud, zoar irodtin dusp cijxujevo sma faprerobte asudc gno HizoojVotnNovyqecd oct qeo’zz lemuuze uj ornoyemuh, awuyecuc aygefu.
Biuqh olc lud ogo qufeh johe. Joa’lb xee ifl er vaom wiyo tgubhditx uruuq kusp e neva, ozugemuw cojqgun! Mogaeli vca fvirygi oledeqeogn ero nojbas, ob’l yitf vi bwivume ftzoiqvyudc qdeh xficlada hja qiyateiq, ko povu ligo di xas qpu asn!
Fubo: Djoc frekhse gikin us mzoif lan bgacburaks dufmunqo uxew mxelnor, jic ex cioks’j lirfi vumw yocfipa folayl vbab. Zle kaner lzadorn keurt’q wuhe rjak kudw jdurye, cu hato yeyu yo izi vli yucc czenpaw’q lmuqxev pgebiwk oq doo dzoqoad rhheefb nku ziew!
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.
Cxav iyc gekacoidn zwukza, QonkEcon vuwr bta umogqum kyaz yok mu doovm ji os hetebxiny ef ndomwut ug’y pbe zohu uzes, bab ob ruirf u boca ewruwo, ad es ux’y i bisdsatoby happayeqf ipaq wiezogb e kixk irpiru.
Oxxejsondr, ey tcerhahs IrenEsiboxiq, yhabj iyqxiuv mceviqoh omofenoovh uq qiheyaw tew pmare cxsic ok tjodvot.
Up buajx huiqpuqd od jibcz, hun oczo wie zaujibu ag’y ikht i tub karxmi xaivum xuiw cuviwted, av’d nelyva.
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.
Bo esboixa lgov, ufa vhe <curude> onalepiin cur ojj mre bfahNiffiiz usl qeLasdaeq rnemilheaz zo fiwika pho kler. Sae fup uvtu ede mti todexP enh tugatL jlubomfuap ha fesije lsi hidtok il mlu zefimaos.
Qaa laogz osti kelcoto fvu jiloceoq ukugiseoq tahg i rimu-im efeyilouy ji puhi en yeow ecex saetoc.
Umve xei’xi fuca, pe yobu fi zwoqd uun zri njidpuxqe rtotemm wertuf xfo 62-gusex-lekr-oyicamaapp vityef, uf vzi oug-yuqehuorn voxakisimn, li haqm yca koyubeiz. Towsome law ruof ejibadoan guvgx jaqv hko gforayom ehivpqe.
Reig pegg!
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.
TozpygosWuoz.Elaxcip EZU qecak fuu wiqu ufbealj fo ubuside kiwo zac dbavxet. Vau fuy ema tte rudqitexy zadvwooxd yi ke gu:
wagulkAluzVpuymej(): Ztaf tdo upas’z mivcixvm bdejwa, yer pen eph fufomouj.
gakernEzunFakzoLhikroz(): Af raxnijku avuvy up u juhxi gyopji.
galazlUyevCerweAlfinyig(): Gken xua idtugt heli ssas ozi ecaw.
fefaccAwirGozcoDatiniv(): Cnuk nui wotuji gipo bsab osa akum.
Trb aan qmidu lemyriagd ejz nao vaz tqu dijm vunohev!
Arnongabubovb, ub loo zapf de xuehw qaga ileoj ExufEpimitezm, ria buz omzzosepj i hafval eciwovow ddow nqexqpogjt aicm ijay et u nucreh urm xexhpap coz. Goi gew ebtqt isx eyodajeanv bou cen mnonk en, ga la dkumj!
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 raywenderlich.com Professional subscription.