socialgekon.com
  • Tärkein
  • Projektinhallinta
  • Trendit
  • Työkalut Ja Oppaat
  • Web-Käyttöliittymä
Matkapuhelin

RxSwift ja animaatiot iOS: ssä

Jos olet iOS-kehittäjä Kuka on tehnyt kohtuullisen määrän käyttöliittymää ja on siitä intohimoinen, sinun on rakastettava UIKitin voimaa animaatioiden suhteen. UIView-animaatio on yhtä helppoa kuin kakku. Sinun ei tarvitse ajatella paljon siitä, miten saada se haalistumaan, kiertymään, liikkumaan tai kutistumaan / laajentumaan ajan myötä. Siihen kuitenkin liittyy vähän, jos haluat ketjuttaa animaatioita yhteen ja asettaa riippuvuuksia niiden välille. Koodisi voi olla lopulta melko yksityiskohtainen ja vaikeasti seurattava, ja siinä on monia sisäkkäisiä sulkemisia ja sisennystasoja.

Tässä artikkelissa tutkin, miten RxSwiftin kaltaisen reaktiivisen kehyksen voimaa voidaan käyttää, jotta koodi näyttää paljon puhtaammalta sekä helpommin luettavalta ja seurattavalta. Idea tuli minulle, kun olin tekemässä projektia asiakkaalle. Kyseinen asiakas oli erittäin käyttöliittymätajuinen (joka sopi täydellisesti intohimoani)! He halusivat sovelluksensa käyttöliittymän käyttäytyvän hyvin erityisellä tavalla, lukuisilla erittäin tyylikkäillä siirtymillä ja animaatioilla. Yksi heidän ideoistaan ​​oli saada käyttöönotto sovellukseen, joka kertoi tarinan siitä, mistä sovelluksessa oli kyse. He halusivat, että tarina kerrotaan animaatioiden sarjan kautta pikemminkin kuin toistamalla ennalta renderöityä videota, jotta se voitaisiin helposti säätää ja virittää. RxSwift osoittautui täydelliseksi valinnaksi tällaiselle ongelmalle, koska toivon, että ymmärrät sen, kun olet viimeistellyt artikkelin.

Lyhyt esittely reaktiiviseen ohjelmointiin

Reaktiivisesta ohjelmoinnista on tulossa katkottua osa, ja se on otettu käyttöön useimmissa moderneissa ohjelmointikielissä. Siellä on paljon kirjoja ja blogeja, joissa selitetään yksityiskohtaisesti, miksi reaktiivinen ohjelmointi on niin tehokas käsite ja kuinka se auttaa kannustamaan hyvää ohjelmistosuunnittelua noudattamalla tiettyjä suunnitteluperiaatteita ja -malleja. Se antaa sinulle myös työkalupaketin, joka voi auttaa vähentämään merkittävästi koodin sotkua.



Haluaisin koskettaa yhtä näkökohtaa, joka todella pidän - helppous, jolla voit ketjuttaa asynkronisia toimintoja ja ilmaista ne selittävällä, helposti luettavalla tavalla.

Swiftin suhteen on kaksi kilpailevaa kehystä, jotka auttavat sinua muuttamaan sen reaktiiviseksi ohjelmointikieleksi: ReactiveSwift ja RxSwift. En käytä RxSwiftia esimerkeissäni siksi, että se olisi parempi, vaan siksi, että tunnen sen paremmin. Oletan, että sinäkin, lukija, tunnet sen hyvin, jotta pääsen suoraan sen lihaan.

Ketjuanimaatiot: Vanha tie

Oletetaan, että haluat kiertää näkymää 180 ° ja sitten häivyttää sen. Voit käyttää completion sulje ja tee jotain tällaista:

UIView.animate(withDuration: 0.5, animations: { self.animatableView.transform = CGAffineTransform(rotationAngle: .pi/2) }, completion: { _ in UIView.animate(withDuration: 0.5) { self.animatableView.alpha = 0 } })

Animoitu GIF pyörivästä neliöstä

Se on vähän iso, mutta silti kunnossa. Mutta entä jos haluat lisätä vielä yhden animaation väliin, sano, siirrä näkymää oikealle sen kiertämisen jälkeen ja ennen kuin se häviää? Soveltamalla samaa lähestymistapaa päädyt jotain tällaiseen:

UIView.animate(withDuration: 0.5, animations: { self.animatableView.transform = CGAffineTransform(rotationAngle: .pi/2) }, completion: { _ in UIView.animate(withDuration: 0.5, animations: { self.animatableView.frame = self.animatableView.frame.offsetBy(dx: 50, dy: 0) }, completion: { _ in UIView.animate(withDuration: 0.5, animations: { self.animatableView.alpha = 0 }) }) })

Suorakulmion animoitu GIF, joka pyörii, pysähtyy ja liukuu sitten oikealle

Mitä enemmän vaiheita siihen lisätään, sitä porrastetumpi ja hankalampi se on. Ja sitten, jos päätät muuttaa tiettyjen vaiheiden järjestystä, joudut suorittamaan jonkin ei-triviaalin leikkaus- ja liittämisjakson, joka on altis virheille.

No, Apple on ilmeisesti ajatellut sitä - he tarjoavat paremman tavan tehdä tämä käyttämällä avainkehykseen perustuvia animaatioiden sovellusliittymää. Tällä lähestymistavalla yllä oleva koodi voidaan kirjoittaa uudestaan ​​seuraavasti:

UIView.animateKeyframes(withDuration: 1.5, delay: 0, options: [], animations: { UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 0.33, animations: { self.animatableView.transform = CGAffineTransform(rotationAngle: .pi/2) }) UIView.addKeyframe(withRelativeStartTime: 0.33, relativeDuration: 0.33, animations: { self.animatableView.frame = self.animatableView.frame.offsetBy(dx: 50, dy: 0) }) UIView.addKeyframe(withRelativeStartTime: 0.66, relativeDuration: 0.34, animations: { self.animatableView.alpha = 0 }) })

Se on iso parannus, ja tärkeimmät edut ovat:

  1. Koodi pysyy tasaisena riippumatta siitä, kuinka monta askelta siihen lisätään
  2. Tilauksen muuttaminen on yksinkertaista (yhden huomautuksen alla)

Tämän lähestymistavan haittana on, että sinun on ajatteltava suhteellisen keston suhteen ja vaiheen absoluuttisen ajoituksen tai järjestyksen muuttaminen on vaikeaa (tai ainakaan ei kovin suoraviivaista). Ajattele vain, mitä laskelmia sinun pitäisi käydä läpi ja millaisia ​​muutoksia sinun tulisi tehdä jokaisen animaation kokonaiskestoon ja suhteelliseen kestoon / aloitusaikaan, jos päätät saada näkymän haalistumaan 1 sekunnissa puolen toinen pitäen kaikki muu ennallaan. Sama pätee, jos haluat muuttaa vaiheiden järjestystä - sinun on laskettava uudelleen niiden suhteelliset aloitusajat.

Ottaen huomioon haitat, en löydä mitään edellä mainituista lähestymistavoista riittävän hyviä. Etsimäni ihanteellisen ratkaisun tulisi täyttää seuraavat ehdot:

  1. Koodin on pysyttävä tasaisena vaiheiden lukumäärästä riippumatta
  2. Minun pitäisi pystyä lisäämään / poistamaan tai järjestämään animaatioita helposti ja muuttamaan niiden kestoa itsenäisesti ilman sivuvaikutuksia muihin animaatioihin

Ketjuanimaatiot: RxSwift Way

Huomasin, että RxSwiftin avulla voin helposti saavuttaa molemmat tavoitteet. RxSwift ei ole ainoa kehys, jota voit käyttää tällaisen tekemiseen - mikä tahansa lupauspohjainen kehys, jonka avulla voit kääriä asynkronointitoiminnot menetelmiin, jotka voidaan ketjuttaa yhteen ketjussa käyttämättä täydennyslohkoja. Mutta RxSwiftillä on paljon enemmän tarjottavaa operaattorivalikoimallaan, jota kosketamme hieman myöhemmin.

Tässä on pääpiirre siitä, miten aion tehdä sen:

  1. Käärin kaikki animaatiot funktioksi, joka palauttaa havaittavissa olevan tyypin Observable.
  2. Tämä havaittava lähettää vain yhden elementin ennen jakson loppuun saattamista.
  3. Elementti lähetetään heti, kun toiminnon käärimä animaatio on valmis.
  4. Ketjutan nämä havaittavissa olevat osat käyttämällä flatMap operaattori.

Näin toimintoni voivat näyttää:

func rotate(_ view: UIView, duration: TimeInterval) -> Observable { return Observable.create { (observer) -> Disposable in UIView.animate(withDuration: duration, animations: { view.transform = CGAffineTransform(rotationAngle: .pi/2) }, completion: { (_) in observer.onNext(()) observer.onCompleted() }) return Disposables.create() } } func shift(_ view: UIView, duration: TimeInterval) -> Observable { return Observable.create { (observer) -> Disposable in UIView.animate(withDuration: duration, animations: { view.frame = view.frame.offsetBy(dx: 50, dy: 0) }, completion: { (_) in observer.onNext(()) observer.onCompleted() }) return Disposables.create() } } func fade(_ view: UIView, duration: TimeInterval) -> Observable { return Observable.create { (observer) -> Disposable in UIView.animate(withDuration: duration, animations: { view.alpha = 0 }, completion: { (_) in observer.onNext(()) observer.onCompleted() }) return Disposables.create() } }

Ja näin laitan kaiken yhteen:

rotate(animatableView, duration: 0.5) .flatMap { [unowned self] in self.shift(self.animatableView, duration: 0.5) } .flatMap { [unowned self] in self.fade(self.animatableView, duration: 0.5) } .subscribe() .disposed(by: disposeBag)

Se on varmasti paljon enemmän koodia kuin edellisissä toteutuksissa, ja se voi näyttää hieman ylenmääräiseltä tällaiselle yksinkertaiselle animaatioille, mutta kauneus on, että sitä voidaan laajentaa käsittelemään joitain melko monimutkaisia ​​animaatiojaksoja ja se on erittäin helppo lukea syntaksin julistava luonne.

Kun saat siitä käsityksen, voit luoda animaatioita niin monimutkaisiksi kuin elokuva ja sinulla on käytettävissänne laaja valikoima käteviä RxSwift-operaattoreita, joita voit käyttää sellaisten asioiden toteuttamiseen, joita olisi erittäin vaikea tehdä millä tahansa edellä mainituista lähestymistavoista.

Näin voimme käyttää .concat operaattori tehdä koodistani vielä suppeampi - osa, jossa animaatiot ketjutetaan yhteen:

Observable.concat([ rotate(animatableView, duration: 0.5), shift(animatableView, duration: 0.5), fade(animatableView, duration: 0.5) ]) .subscribe() .disposed(by: disposeBag)

Voit lisätä viiveitä tällaisten animaatioiden väliin:

func delay(_ duration: TimeInterval) -> Observable { return Observable.of(()).delay(duration, scheduler: MainScheduler.instance) } Observable.concat([ rotate(animatableView, duration: 0.5), delay(0.5), shift(animatableView, duration: 0.5), delay(1), fade(animatableView, duration: 0.5) ]) .subscribe() .disposed(by: disposeBag)

Oletetaan nyt, että haluamme näkymän kiertyvän tietyn määrän kertoja ennen kuin se alkaa liikkua. Ja haluamme säätää helposti, kuinka monta kertaa sen pitäisi pyöriä.

Ensin teen menetelmän, joka toistaa rotaatioanimaation jatkuvasti ja lähettää elementin jokaisen kierroksen jälkeen. Haluan, että nämä kierrot pysähtyvät heti, kun havaittava on hävitetty. Voisin tehdä jotain tällaista:

func rotateEndlessly(_ view: UIView, duration: TimeInterval) -> Observable { var disposed = false return Observable.create { (observer) -> Disposable in func animate() { UIView.animate(withDuration: duration, animations: { view.transform = view.transform.rotated(by: .pi/2) }, completion: { (_) in observer.onNext(()) if !disposed { animate() } }) } animate() return Disposables.create { disposed = true } } }

Ja sitten kaunis animaatioketjuni voisi näyttää tältä:

Observable.concat([ rotateEndlessly(animatableView, duration: 0.5).take(5), shift(animatableView, duration: 0.5), fade(animatableView, duration: 0.5) ]) .subscribe() .disposed(by: disposeBag)

Näet kuinka helppoa on hallita kuinka monta kertaa näkymä pyörii - muuta vain take operaattori.

Parannetun animaation animoitu GIF

Haluaisin nyt viedä toteutukseni askeleen pidemmälle käärimällä ne kaikki, jos luomani animaatiotoiminnot UIView: n 'Reactive' -laajennukseen (pääsee .rx -liitteen kautta). Tämä tekisi siitä enemmän RxSwift-käytäntöjen mukaisesti, joissa reaktiivisiin toimintoihin pääsee yleensä .rx pääte, jotta voidaan tehdä selväksi, että he palaavat havaittavissa oleviin.

extension Reactive where Base == UIView { func shift(duration: TimeInterval) -> Observable { return Observable.create { (observer) -> Disposable in UIView.animate(withDuration: duration, animations: { self.base.frame = self.base.frame.offsetBy(dx: 50, dy: 0) }, completion: { (_) in observer.onNext(()) observer.onCompleted() }) return Disposables.create() } } func fade(duration: TimeInterval) -> Observable { return Observable.create { (observer) -> Disposable in UIView.animate(withDuration: duration, animations: { self.base.alpha = 0 }, completion: { (_) in observer.onNext(()) observer.onCompleted() }) return Disposables.create() } } func rotateEndlessly(duration: TimeInterval) -> Observable { var disposed = false return Observable.create { (observer) -> Disposable in func animate() { UIView.animate(withDuration: duration, animations: { self.base.transform = self.base.transform.rotated(by: .pi/2) }, completion: { (_) in observer.onNext(()) if !disposed { animate() } }) } animate() return Disposables.create { disposed = true } } } }

Sen avulla voin koota ne yhteen näin:

Observable.concat([ animatableView.rx.rotateEndlessly(duration: 0.5).take(5), animatableView.rx.shift(duration: 0.5), animatableView.rx.fade(duration: 0.5) ]) .subscribe() .disposed(by: disposeBag)

Minne mennä täältä

Kuten tämä artikkeli havainnollistaa, vapauttamalla RxSwiftin voima ja kun primitiivisi ovat paikallaan, voit pitää hauskaa animaatioiden kanssa. Koodisi on puhdas ja helppo lukea, eikä se näytä enää koodilta - kuvailet kuinka animaatiosi kootaan ja ne vain heräävät eloon! Jos haluat tehdä jotain monimutkaisempaa kuin tässä on kuvattu, voit varmasti tehdä sen lisäämällä enemmän omia kapselointisi muuntyyppisiä animaatioita. Voit myös aina hyödyntää jatkuvasti kasvavaa työkalujen ja kehysten arsenaalia, jonka jotkut intohimoiset ihmiset ovat kehittäneet avoimen lähdekoodin yhteisössä.

Jos olet RxSwift-muuntaja, jatka vierailua RxSwiftCommunity-arkisto säännöllisesti: löydät aina jotain uutta!

Jos etsit lisää käyttöliittymäneuvoja, kokeile lukea Kuinka toteuttaa Pixel-täydellinen iOS-käyttöliittymäsuunnittelu kirjoittanut ApeeScapeer Roman Stetsenko.


Lähdetiedot (Perustietojen ymmärtäminen)

  • Wikipedia - Swift (ohjelmointikieli)
  • Lynda.com - RxSwift: Suunnittelumallit iOS-kehittäjille
  • We Heart Swift - UIView-perusteet
  • Kulma - havaittavissa

Perustietojen ymmärtäminen

Mihin Swiftia käytetään?

'Swift on yleiskäyttöinen, moniparadigmainen, käännetty ohjelmointikieli, jonka Apple Inc. on kehittänyt iOS-, macOS-, watchOS-, tvOS-, Linux- ja z / OS-käyttöjärjestelmille. Swift on suunniteltu toimimaan Applen Cocoa- ja Cocoa Touch -kehysten ja Applen tuotteille kirjoitettujen olemassa olevien Objective-C-koodien kanssa. ''

Mikä on UIVIew iOS: ssä?

'UIView-luokka määrittää suorakulmaisen alueen ruudulla, jolla se näyttää sisältöä. Se hoitaa minkä tahansa alueen sisällön renderoinnin ja myös kaikki vuorovaikutukset kyseisen sisällön kanssa - kosketukset ja eleet. '

Mitä reaktiivisella ohjelmoinnilla tarkoitetaan?

Reaktiivinen ohjelmointi on asynkroninen ohjelmointiparadigma, joka koskee asynkronisia datavirtoja ja muutoksen etenemistä.

Mikä on RxSwift?

RxSwift on reaktiivinen ohjelmointikirjasto iOS: lle. Sen avulla on helppo ohjelmoida dynaamisia sovelluksia, jotka vastaavat tietojen muutoksiin ja käyttäjän tapahtumiin.

Mikä on havaittavissa?

Havainnoitavat kohteet tarjoavat tukea viestien lähettämiseen julkaisijoiden ja tilaajien välillä sovelluksessasi. Havaittavat muuntavat datavirrat tapahtumasarjaksi, joka toimitetaan yhdelle tai useammalle tilaajalle asynkronisesti.

Sivunopeus 101: Säätiö mobiilikäyttöliittymäsuunnittelijoille

Mobiilisuunnittelu

Sivunopeus 101: Säätiö mobiilikäyttöliittymäsuunnittelijoille
Suunnittelu ihmisen käyttäytymiseen: Aineettoman määritteleminen

Suunnittelu ihmisen käyttäytymiseen: Aineettoman määritteleminen

Ux-Suunnittelu

Suosittu Viestiä
Onko Yhdysvaltain oman pääoman joukkorahoitusmarkkinat eläneet odotuksia?
Onko Yhdysvaltain oman pääoman joukkorahoitusmarkkinat eläneet odotuksia?
Fintech-teollisuuden tila (infografiikan kanssa)
Fintech-teollisuuden tila (infografiikan kanssa)
10 Yleisimmät verkkoturvan haavoittuvuudet
10 Yleisimmät verkkoturvan haavoittuvuudet
Kuka tiesi Adobe CC: n voivan kehystää?
Kuka tiesi Adobe CC: n voivan kehystää?
Opas UTF-8-koodaukseen PHP: ssä ja MySQL: ssä
Opas UTF-8-koodaukseen PHP: ssä ja MySQL: ssä
 
Fintech ja pankit: Kuinka pankkisektori voi reagoida häiriöiden uhkaan?
Fintech ja pankit: Kuinka pankkisektori voi reagoida häiriöiden uhkaan?
Shopify-suunnitteluvinkit ja UX: n parhaat käytännöt
Shopify-suunnitteluvinkit ja UX: n parhaat käytännöt
Suorita matematiikka: Mikropalvelusovellusten skaalaus orkesterin kanssa
Suorita matematiikka: Mikropalvelusovellusten skaalaus orkesterin kanssa
Aloittelijan opas vedenalaiseen valokuvaukseen iPhonella
Aloittelijan opas vedenalaiseen valokuvaukseen iPhonella
Motivaation säännöt: Tarina epäonnistuneiden myyntikannustinjärjestelmien korjaamisesta
Motivaation säännöt: Tarina epäonnistuneiden myyntikannustinjärjestelmien korjaamisesta
Luokat
Tuotemerkin SuunnitteluWeb-KäyttöliittymäVarastointiKetterä KykyLähettäminenIhmiset Ja JoukkueetSijoittajat Ja RahoitusTuotteen ElinkaariProsessi Ja TyökalutLiikevaihdon Kasvu

© 2023 | Kaikki Oikeudet Pidätetään

socialgekon.com