Illustratsioon: Virginia Poltrack

Kava järgi animeerimine

Animatsioonid rakenduses Google I / O

Olin hiljuti osa suurepärasest meeskonnast, kes töötab Google Android I 2018 rakendusega. See on konverentsikaaslase rakendus, mis võimaldab osalejatel ja kaugetel inimestel leida seansse, koostada isikupärastatud ajakava ja reserveerida kohad kohapeal (kui teil on seal kohal õnne!). Ehitasime rakendusse mitmeid huvitavaid animeeritud funktsioone, mis minu arvates parandasid kogemusi märkimisväärselt. Selle rakenduse kood on just avatud lähtekoodiga ja soovisin esile tõsta mõnda neist juhtumitest ning huvitavaid rakenduse üksikasju.

Mõned animeeritud elemendid I / O-rakenduses

Üldiselt on rakenduses 3 tüüpi animatsioone:

  1. Kangelasanimatsioonid - kasutatakse brändingu tugevdamiseks ja rõõmu pakkuvateks hetkedeks
  2. Ekraani üleminekud
  3. Riigi muutused

Ma tahaksin neist mõne üksikasjalikult käsitleda.

Tagaplaanil

Rakenduse osa on konverentsil põnevust ja ootust üles ehitada. Sel aastal hõlmasime konverentsi alguse jaoks suure animeeritud tagasiarvestuse, mida kuvati nii pardaletuleku ekraanil kui ka jaotises Info. See oli ka suurepärane võimalus sündmuse kaubamärgi kinnistamiseks rakendusse, mis toob palju iseloomu.

Konverentsi algusaeg algab

Animatsiooni kujundas liikumiskujundaja ja see jagati välja Lottie jsoni failide seeriana: iga 1 sekundi pikkune number näitab animatsiooni "sisse", siis "välja". Lottie-vorming tegi failide varadesse langemise hõlpsaks ja pakkus isegi mugavusmeetodeid, näiteks setMinAndMaxProgress, mis võimaldas meil mängida vaid animatsiooni esimest või viimast poolt (näidata numbrit, mis animeerib sisse või välja).

Huvitav osa oli tegelikult nende mitme animatsiooni orkestreerimine üldisesse loendusse. Selleks lõime kohandatud CountdownView, mis on üsna keeruline ConstraintLayout, mis sisaldab mitmeid LottieAnimationViews. Sellega lõime Kotlini delegaadi, et kapselduda vastava animatsiooni käivitamisest. See võimaldas meil lihtsalt määrata igale kuvatava numbri delegaadile int ning delegaat seadistaks ja käivitaks animatsiooni (d). Pikendasime ObservableProperty esindajat, mis tagab, et animatsiooni tegime ainult siis, kui number muutub. Seejärel postitas meie animatsioonisilm iga sekundi (kui vaade on lisatud) käitatava käigu, mis arvutas välja, millist numbrit iga vaade peaks kuvama, ja uuendas delegaate.

Broneerimine

Üks rakenduse võtmetoiminguid on osalejatele vabade kohtade andmine. Sellisena näitasime seda toimingut FAB-is nähtavalt seansi üksikasjade ekraanil. Pidasime oluliseks teatada, et seanss reserveeriti alles siis, kui see on taustal edukalt lõpule jõudnud (erinevalt vähem olulistest toimingutest, nagu näiteks seansi peaosas, kus värskendame kasutajaliidest kohe optimistlikult). See võib võtta natuke aega, kuni ootame taustaprogrammi vastust, nii et reageeritavamaks muutmiseks kasutasime animeeritud ikooni, et anda tagasisidet, et töötame selle kallal ja sujuvalt uude olekusse üleminekuks.

Tagasiside istungil koha reserveerimisega

Seda teeb keeruliseks asjaolu, et selle ikooni kajastamiseks oli mitu riiki: seanss võib olla reserveeritav, nad võivad olla juba koha broneerinud, kui seanss on täis, võib olla saadaval ooteloend või nad võivad olla ootenimekiri või seansi alguse lähedal reserveerimine on keelatud. Selle tulemuseks oli mitmesuguste olekute permutatsioonide vaheline animeerimine. Nende üleminekute lihtsustamiseks otsustasime minna alati läbi töötava oleku; ülaltoodud animeeritud liivakell. Seetõttu koosneb iga üleminek tegelikult paarist: olek 1 → töötab ja töötab → olek 2. See lihtsustas asju oluliselt. Ehitasime kõik need animatsioonid kujuvahendaja abil; vaata siin faile avd_state_to_state.

Selle kuvamiseks kasutasime kohandatud vaadet ja AnimatedStateListDravable (ASLD). Kui te pole varem ASLD-d kasutanud, on see (nagu nimigi viitab) animeeritud versioon StateListDravableist, millega olete tõenäoliselt kokku puutunud - see võimaldab teil mitte ainult pakkuda erinevaid draivereid oleku kohta, vaid ka üleminekuid olekute vahel (animeeritudVectorDravable kujul) või AnimationDravable). Siin on joonis, mis määratleb staatilised pildid ja üleminekud tööoleku olekusse ja sealt välja reserveerimise ikooni jaoks.

Lõime kohandatud vaate omaenda olekute toetamiseks. Vaated pakuvad mõnda standardset olekut, näiteks vajutatud või valitud. Samamoodi saate määratleda oma ja omada marsruuti Kuva mis tahes draiverites, mida see kuvab. Me määratlesime oma oleku_reserveeritav, oleku_reserveeritud jne. Seejärel koostasime nende erinevate olekute loendi, kapseldades vaate oleku koos kõigi seotud atribuutidega, näiteks seotud sisu kirjeldusega. Meie äriloogika võiks siis lihtsalt selle vaate põhjal (andmete sidumise kaudu) seada sobiva väärtuse, mis värskendaks joonise olekut, mis käivitas animatsiooni ASLD-i kaudu. Kohandatud olekute ja AnimatedStateListDravable kombinatsioon oli selle rakendamiseks hea viis, hoides arvukaid olekuid deklaratiivsetes kihtides, mille tulemuseks oli minimaalne vaatekood.

Kõlarite üleminek

Paljud ekraanide üleminekud töötasid tavaliste aknaanimatsioonidega hästi. Üks koht, millest me sellest kaldusime kõrvale, on üleminek kõlari üksikasjade ekraanile. See näitas kõlarite pilti ülemineku mõlemal küljel ja oli ideaalne kandidaat ühiste elementide üleminekuks. See aitab hõlbustada kontekstivahetust ekraanide vahel.

Jagatud elemendi üleminek

See on üsna tavaline jagatud elemendi üleminek, kasutades ImageView-platvormi ChangeBounds ja ArcMotion.

Huvitavam on see, kuidas selle ülemineku algatamine sobis sündmuste mustriga, mida me navigeerimisel kasutasime. Põhimõtteliselt eraldab see muster sisestussündmused (näiteks kõlarile koputamine) navigatsioonisündmustest, pannes ViewModeli vastutama sisendile reageerimise eest. Sel juhul tähendab see lahtisidumine, et ViewModel paljastas sündmuste LiveData, mis teadis ainult kõneleja ID-d, kuhu navigeerida. Jagatud elemendi ülemineku algatamiseks on vaja ühist vaadet, mida meil sel hetkel polnud. Lahendasime selle, salvestades kõlari ID siltidena vaates, kui see on seotud, nii et vaade oleks hiljem taastatav, kui peame navigeerima konkreetsesse kõlarite üksikasjade ekraanile.

Filtrid

Konverentsirakenduse põhiosa on paljude sündmuste filtreerimine kuni huvipakkuvateni. Igal teemal oli sellega hõlpsasti äratundmiseks värviga seostatud ja me saime suurepärase kujunduse kohandatud „kiibiks”, mida kasutada filtrite valimisel:

Animeeritud filterkiibid

Vaatasime kiipi materjalikomponentidest, kuid otsustasime rakendada oma kohandatud vaadet, et kuvatud oleku ja animatsiooni suuremat kontrolli "kontrollitud" olekute vahel kontrollida. Selle rakendamiseks kasutatakse lõuendi joonistamist ja StaticLayout teksti kuvamiseks. Vaatel on üksainus edenemisomadus [0–1], modelleerimine märkimata - kontrollitud. Olekute vahetamiseks animeerime seda väärtust lihtsalt ja muudame vaate kehtetuks ning renderduskood interpoleerib selle põhjal elementide positsioonid ja suurused lineaarselt.

Esialgu selle rakendamisel tegin vaatel kontrollitava liidese ja käivitasin animatsiooni, kui setChecked meetod seadis uue oleku. Kuna me kuvame rakenduses RecyclerView mitu filtrit, oli animatsiooni käivitamisel see kahetsusväärne efekt, kui valitud filter keriti välja ja vaade tagasilöögiks valimata filtrile keris sisse. Seetõttu lisasime animatsiooni käivitamiseks eraldi meetodi, mis võimaldab meil vahet teha, kui siduda see klõpsuga ja kohest värskendamist, kui seotakse uusi andmeid vaatega.

Lisaks sellele lülitasime selle lülitatava animatsiooni tutvustades, et see on janking, st kaadrite kukutamine. Kas süüdi oli minu animatsioonikood? Neid filtreid kuvatakse põhjalehel konverentsi peamise ajakava ekraani ees. Kui filter on ümber lülitatud, käivitame ajakavale rakendatava filtreerimisloogika (ja värskendame filtrilehe pealkirjas sobivate sündmuste arvu). Mõningane hiljem ilmnenud süsteerium leidis, et probleem oli selles, et filtrite rakendamisel läks ajakava kohusetundlikult kuvav RecyclerViews ViewPager välja ja värskendati värskelt edastatud andmetega. See põhjustas paljude vaadete suurendamise ja seotuse. Kogu see töö lõi meie raamieelarvesse ... kuid värskendamiskava ei olnud nähtav, kuna see oli filtrilehe taga. Otsustasime tegeliku filtreerimise edasilükkamise edasi lükata, kuni animatsioon oli käima läinud, ja sujuvama kasutajakogemuse nimel läksime veel keerukamaks. Algselt rakendasin seda postDelayed abil, kuid see tekitas kasutajaliidese testides probleeme. Selle asemel vahetasime animatsiooni alustanud meetodit, et aktsepteerida lambda lõpptulemusena käivitamist. See võimaldas meil paremini austada kasutaja animatsiooniseadeid ja testida täitmist korralikult.

Hankige animeeritud

Üldiselt tunnen, et animatsioonid aitasid tõepoolest kaasa rakenduse kogemusele, iseloomule, brändingule ja reageerimisele. Loodetavasti on see postitus aidanud selgitada, miks ja kuidas neid kasutati, ning andnud teile näpunäited nende rakendamiseks.