Kuva Virginia Poltrack

Animointi aikataulussa

Animaatioita Google I / O -sovelluksessa

Olin hiljattain osa hienoa tiimiä, joka työskentelee Google I / O 2018 Android-sovelluksen kanssa. Tämä on konferenssikaverisovellus, jonka avulla osallistujat ja etäyhteisöt voivat löytää istuntoja, rakentaa henkilökohtaisen aikataulun ja varata paikkoja tapahtumapaikalle (jos olet tarpeeksi onnekas paikalla!). Rakensimme sovellukseen useita mielenkiintoisia animoituja ominaisuuksia, joiden uskon paranneen kokemusta huomattavasti. Tämän sovelluksen koodi on juuri avoin lähde ja halusin tuoda esiin muutamia näistä tapauksista ja mielenkiintoisia toteutustietoja.

Jotkut animoidut elementit I / O-sovelluksessa

Yleensä sovelluksessa käytetään 3 tyyppisiä animaatioita:

  1. Hero-animaatiot - käytetään vahvistamaan tuotemerkkiä ja tuomaan iloisia hetkiä
  2. Näytön muutokset
  3. Valtion muutokset

Haluaisin syventää muutamia näistä.

Lähtölaskenta

Osa sovelluksen tehtävästä on luoda jännitystä ja ennakointia konferenssille. Sellaisena tänä vuonna olemme sisällyttäneet suuren animoidun lähtölaskennan konferenssin alkuun, joka näkyy sekä aluksella näytöllä että tietoosassa. Tämä oli myös loistava tilaisuus upottaa tapahtuman brändäys sovellukseen tuoden paljon merkkiä.

Konferenssin lähtölaskenta alkaa

Tämän animaation on suunnitellut liikkeen suunnittelija ja se luovutettiin sarjana Lottie json-tiedostoja: jokainen yhden sekunnin pituinen osoittaa numeroa, joka animoi 'sisään', 'ulos'. Lottie-muoto antoi tiedostojen pudottamisen helpoksi omaisuuteen ja tarjosi jopa mukavuusmenetelmiä, kuten setMinAndMaxProgress, jonka ansiosta voimme toistaa vain animaation ensimmäisen tai viimeisen puolikkaan (näyttää numeron animoivan tai ulos).

Mielenkiintoinen osa oli näiden useiden animaatioiden järjestämistä kokonaan lähtölaskentaan. Tätä varten loimme mukautetun CountdownView-arvon, joka on melko monimutkainen ConstraintLayout, joka sisältää useita LottieAnimationView-tiedostoja. Tässä perustimme Kotlin-edustajan koteloimaan asianmukaisen animaation käynnistämisen. Tämän ansiosta voimme yksinkertaisesti määrittää Int jokaiselle edustajalle sen numeron, jonka pitäisi näkyä, ja edustaja perustaa ja aloittaa animaation. Laajensimme ObservableProperty-edustajaa, joka varmistaa, että animaatioita käytettiin vain, kun numero muuttuu. Animaatiosilmukka julkaisi sitten yksinkertaisesti ajettavan joka sekunti (kun näkymä on liitetty), joka laski, minkä numeron kunkin näkymän pitäisi näyttää, ja päivitti edustajat.

Varaus

Yksi sovelluksen avaintoiminnoista on osallistujien varaaminen paikkoihin. Sellaisena me näytimme tämän toiminnan näkyvästi FAB: ssa istunnon yksityiskohdat -näytössä. Mielestämme oli tärkeää ilmoittaa vain, että istunto varattiin vasta sen jälkeen, kun se on onnistuneesti suoritettu loppuun taustalla (toisin kuin vähemmän tärkeät toiminnot, kuten tähdellä istunto, jonka aikana päivitämme käyttöliittymän optimistisesti välittömästi). Tämä voi viedä hetken, kun odotamme vastausta taustaohjelmasta, joten vastaamiseksi reagointiin käytimme animoitua kuvaketta antamaan palautetta siitä, että työskentelemme sen kanssa, ja siirtyä sujuvasti uuteen tilaan.

Palaute varaamalla paikka istuntoon

Tätä monimutkaistaa se, että oli useita valtioita, joita tämän kuvakkeen on heijastettava: istunto voi olla varattavissa, ne ovat jo voineet varata paikan, jos istunto on täynnä, odotuslista saattaa olla saatavana tai ne voivat olla odotuslista tai lähellä istunnon aloitusvarauksia poistetaan käytöstä. Tämä johti monien erilaisten tilojen permutaatioihin animoida välillä. Näiden siirtymien yksinkertaistamiseksi päätimme aina käydä läpi toimivan tilan; yllä oleva animoitu tiimalasi. Siksi jokainen siirtymä on oikeastaan ​​pari: tila 1 → toimiva & työskentelevä → tila 2. Tämä yksinkertaisti asioita suuresti. Rakensimme kaikki nämä animaatiot käyttämällä muodonmuutosohjelmaa; katso avd_state_to_state-tiedostot täältä.

Tämän näyttämiseksi käytimme mukautettua näkymää ja AnimatedStateListDravable (ASLD). Jos et ole aiemmin käyttänyt ASLD: tä, se on (kuten nimensä viittaa) animoitu StateListDravable-versio, johon olet todennäköisesti kohdannut - antaa sinun tarjota paitsi erilaisia ​​vetolaitteita tilaa kohti, mutta myös siirtymiä tilojen välillä (AnimatedVectorDravable-muodossa) tai AnimationDravable). Tässä on piirustus, joka määrittelee staattiset kuvat ja muutokset varaustilan kuvaketta varten työskentelytilaan ja pois käytöstä.

Loimme mukautetun näkymän tukemaan omia mukautettuja tiloja. Näkymät tarjoavat joitain vakiotiloja, kuten painettu tai valittu. Samoin voit määrittää oman ja saada Näytä reitin mihin tahansa näytettäviin piirroksiin. Määrittelimme oman tilaansa varautuvan, tilavarannon jne. Luomme sitten näiden eri tilojen enuman, kapseloimalla näkymän tilan ja kaikki siihen liittyvät määritteet, kuten liittyvä sisältökuvaus. Liikelogiikkamme voisi sitten asettaa sopivan arvon tästä näkymän enumasta (tietojen sitomisen kautta), joka päivittäisi piirretyn tilan, joka aloitti animaation ASLD: n kautta. Mukautettujen tilojen ja AnimatedStateListDravable-yhdistelmä oli siisti tapa toteuttaa tämä, pitämällä lukuisat tilat deklaratiivisissa kerroksissa, mikä tuotti minimaalisen näkymäkoodin.

Kaiutinsiirto

Monet näytön siirtymistä toimivat hyvin vakioikkunoiden animaatioiden kanssa. Yksi paikka, josta poikimme tästä, on siirtyminen kaiuttimen yksityiskohtien näyttöruutuun. Tämä näytti kaiuttimien kuvan siirtymisen kummallakin puolella ja oli täydellinen ehdokas jaettuun elementtimuutokseen. Tämä auttaa helpottamaan kontekstin vaihtamista näyttöjen välillä.

Jaettu elementtisiirto

Tämä on melko tavallinen jaettu elementtisiirto, joka käyttää ImageView-järjestelmässä ChangeBounds- ja ArcMotion-luokkia.

Mielenkiintoisempaa on se, kuinka tämän siirtymisen aloittaminen sopi tapahtumasuunnitelmaan, jota käytimme navigointiin. Pohjimmiltaan tämä malli erottaa tulotapahtumat (kuten nauhoittaminen kaiuttimeen) navigointitapahtumista ja asettaa ViewModelin vastuuseen tuloon vastaamiseen. Tässä tapauksessa tämä erottaminen tarkoittaa, että ViewModel paljasti LiveData of Events -tapahtuman, joka tiesi vain puhujan tunnuksen, johon navigoida. Jaetun elementin siirtymisen aloittaminen vaatii jaetun näkymän, jota meillä ei tässä vaiheessa ollut. Ratkaisimme tämän tallentamalla puhujan tunnuksen tunnisteena näkymään, kun se on sidottu, jotta näkymä voidaan myöhemmin noutaa, kun meidän on siirryttävä tiettyyn puhujan yksityiskohtien näyttöön.

Suodattimet

Keskeinen osa konferenssisovellusta suodattaa monet tapahtumat kiinnostaville henkilöille. Jokaiselle aiheelle oli liitetty väri helppoa tunnistamista varten. Saimme suurenmoisen suunnittelun mukautetulle sirulle, jota voidaan käyttää suodattimia valittaessa:

Animoidut suodatinpiirit

Tarkastelimme Chip materiaalikomponenteista, mutta päätimme toteuttaa oman mukautetun näkymämme näytön ja animaation hallinnan parantamiseksi tarkistettujen tilojen välillä. Tämä toteutetaan käyttämällä piirtoalustan piirtämistä ja StaticLayout-tekstiä tekstin näyttämiseen. Näkymässä on yksi edistymisominaisuus [0–1] mallintamatta jättämättä - valittu. Vaihtaaksesi tilan, animoimme tämän arvon ja mitätöidä näkymän, ja renderointikoodi interpoloi lineaarisesti elementtien sijainnit ja koot tämän perusteella.

Aluksi toteuttaessani tätä, tein näkymän toteuttamaan tarkistettavan käyttöliittymän ja aloitin animaation, kun setChecked-menetelmä asetti uuden tilan. Kun näytämme useita suodattimia RecyclerView-näytössä, animaation suorittamisella oli valitettava vaikutus, jos valittu suodatin vieritettiin ja näkymä palautui valittamattomaan suodattimeen, joka vierii sisään. Hups. Siksi lisäsimme erillisen menetelmän animaation käynnistämiseksi, jotta voimme erottaa sen napsautuksella vaihtamisen välitöntä päivitystä sidottaessa uutta tietoa näkymään.

Lisäksi kun esittelemme tämän kytkentäanimaation, huomasimme sen olevan janking eli pudottamassa kehyksiä. Oliko animaatiokoodini syyllinen? Nämä suodattimet näytetään BottomSheet-konferenssissa konferenssin aikataulunäytön edessä. Kun suodatin vaihdetaan, aloitamme aikataululle sovellettavan suodatuslogiikan (ja päivitämme vastaavien tapahtumien määrän suodatinsivun otsikossa). Jotkut myöhemmin ilmestyvästä systraceista päättivät, että ongelmana oli, että suodattimia käytettäessä RecyclerViews-ohjelman ViewPager, joka esitti aikataulun vastuullisesti, meni pois ja päivitettiin äskettäin toimitettuihin tietoihin. Tämä aiheutti useiden näkymien paisumisen ja sidonnan. Kaikki tämä työ puhallesi kehysbudjettiamme ... mutta päivitysaikataulu ei ollut näkyvissä, koska se oli suodatinsivun takana. Päätimme lykätä varsinaisen suodatuksen suorittamista, kunnes animaatio oli käynnissä. Vaihdamme käyttöönoton monimutkaisuutta entistä sujuvamman käyttökokemuksen saamiseksi. Aluksi toteutin tämän postDelayed-sovelluksella, mutta tämä aiheutti ongelmia käyttöliittymätesteissä. Sen sijaan vaihdoimme menetelmän, joka aloitti animaation, hyväksyäkseen loppua ajavan lambdan. Tämän ansiosta voimme paremmin kunnioittaa käyttäjän animaatioasetuksia ja testata suorituksen oikein.

Hanki animoitu

Kaiken kaikkiaan tunnen, että animaatiot todella auttoivat sovelluksen kokemuksessa, luonteessa, brändäyksessä ja reagoivuudessa. Toivottavasti tämä viesti on auttanut selittämään sekä miksi että miten niitä käytettiin, ja antanut sinulle viitteitä niiden toteuttamiseen.