En nybegynnerguide for å implementere Android-animasjoner - Del 1 (2-delerserie)

Innrøm det, du har alltid ønsket å lage visuelt tiltalende apper. Men på grunn av funksjonalitetens første tilnærming ble animasjoner alltid utsatt. Ikke nå lenger.

Litt grunnleggende om animasjoner:

Det er tre typer animasjoner:

  1. Eiendomsanimasjoner - De brukes til å endre eiendommer til objekter (visninger eller objekter som ikke vises). Vi spesifiserer visse egenskaper (som translateX, TextScaleX) av objektene som skal endres. Ulike egenskaper ved animasjon som kan manipuleres er animasjonens varighet, om de skal reverseres og hvor mange ganger vi vil gjenta animasjonen osv. De ble introdusert i Android 3.0 (API-nivå 11).
  2. Se animasjoner - De brukes til å gjøre enkle animasjoner som å endre størrelse, posisjon, rotasjon, kontrollere gjennomsiktighet. De er enkle å bygge og er veldig raske, men har sine egne begrensninger. For f.eks - Deres tilstand endres, men deres eiendom endres ikke. Se animasjoner vil bli dekket i del 2.
  3. Tegnbare animasjoner - Dette brukes til å gjøre animasjoner ved bruk av trekkplater. Det lages en XML-fil som spesifiserer forskjellige lister med tegninger som kjøres en etter en akkurat som en rull av en film. Dette er ikke mye brukt, så jeg vil ikke dekke det.
Android 5.0 introduserte forskjellige andre animasjoner - Reveal Effect, Activity / Fragment overganger, Shared Element overganger etc. Klikk her for å lære mer om dette.
Merk - Del 1 vil kun diskutere eiendomsanimasjoner.

Når skal du bruke hvilken type animasjon

  1. Hvis du bare vil gjøre enkle animasjoner på visninger uten å måtte håndtere andre detaljer som berøring eller klikk, kan du bruke Vis animasjoner. Problemet med View Animations er at selv om View-tilstand endres, forblir eiendommen fortsatt på den opprinnelige plasseringen. Det betyr at hvis en ImageButton blir flyttet fra 0 til 100 piksler til høyre, selv om den vil animere til høyre, vil berøringen (egenskapen) til bildeknappen fortsatt være på 0nde posisjon.
  2. Vis animasjoner kan brukes i Splash-skjermer. Når du bruker Vis animasjoner, bruk XML i stedet for å gjøre det programmatisk. Ved bruk av XML-filer er den mer lesbar og kan deles mellom andre visninger.
  3. Hvis du vil håndtere berøringen, klikker du etter animasjonen, går etter Eiendom Animasjon da de endrer tilstand så vel som atferd.

Eiendomsanimasjonskonsepter

Inne i eiendomsanimasjon. Med tillatelse fra Google.

Selve animasjonen gjøres av Value Animator. Denne klassen holder oversikt over animasjonens varighet og den nåværende verdien av eiendommen som den animerer. TimeInterpolater holder oversikt over animasjonens tid (hastighet) som om det er med konstant hastighet i den gitte tiden, eller akselerer og deretter bremser opp i den gitte tiden. TypeEvaluator brukes til å beregne brøk basert på typen TypeEvalutor brukt for f.eks, int, float, rgb etc. Vi kan bruke en tilpasset TypeEvaluator også hvis ingen samsvarer med våre behov.

Animasjoner ved hjelp av ValueAnimator

I ValueAnimator-klassen kan du animere verdier av en eller annen type i løpet av en animasjon ved å spesifisere et sett med int, float eller fargeverdier du vil animere gjennom. Du skaffer deg en ValueAnimator ved å kalle en av fabrikkmetodene sine: ofInt (), ofFloat () eller ofObject (). For eksempel:

final TextView animateTextView = (TextView) findViewById (R.id.tv_animate);

ValueAnimator valueAnimator = ValueAnimator.ofFloat (0f, 500f);
valueAnimator.setInterpolator (ny AccelerateDecelerateInterpolator ()); // Øk farten først og senk deretter
valueAnimator.setDuration (2000);
valueAnimator.addUpdateListener (ny ValueAnimator.AnimatorUpdateListener () {
    @Overstyring
    public void onAnimationUpdate (Animasjon av verdiAnimator) {
        float progress = (float) animasjon.getAnimatedValue ();
        animateTextView.setTranslationY (fremgang);
        // ingen grunn til å bruke ugyldiggjøre () ettersom den allerede er til stede i // tekstvisningen.
    }
});
valueAnimator.start ();
Med tillatelse fra Giphy

Det samme kan oppnås ved å bruke XML-kode som følger:

                   /res/animator/value_animator_ex.xml

                     ---- Aktivitetskode ----
ValueAnimator valueAnimator = (ValueAnimator) AnimatorInflater.loadAnimator (
        dette, R.animator.value_animator_ex);

valueAnimator.addUpdateListener (ny ValueAnimator.AnimatorUpdateListener () {
    @Overstyring
    public void onAnimationUpdate (Animasjon av verdiAnimator) {
        float progress = (float) animasjon.getAnimatedValue ();
        animateTextView.setTranslationY (fremgang);
    }
});

valueAnimator.start ();

Animasjoner ved hjelp av ObjectAnimator

ObjectAnimator er en underklasse av ValueAnimator og kombinerer tidsstyringsmotoren og beregningen av verdi av ValueAnimator med muligheten til å animere en navngitt egenskap til et målobjekt. Dette gjør animering av ethvert objekt mye enklere, fordi du ikke lenger trenger å implementere ValueAnimator.AnimatorUpdateListener, fordi den animerte egenskapen oppdateres automatisk. I de fleste tilfeller bør vi bruke dette.

For den samme animasjonen over kan vi skrive koden for ObjectAnimator som:

TextView animateTextView = (TextView) findViewById (R.id.tv_animate);

ObjectAnimator textViewAnimator = ObjectAnimator.ofFloat (animateTextView, "translationY", 0f, 500f);
textViewAnimator.setDuration (2000);
textViewAnimator.setInterpolator (ny AccelerateDecelerateInterpolator ());
textViewAnimator.start ();

Som vi ser, trengte vi ikke å bruke lytter for å oppdatere plasseringen av tekstvisningen, da dette er gjort av ObjectAnimator selv. Det viktigste her å se er "translationY" som er egenskapen vi ønsker å utføre animasjon på. Dette skal være en definert egenskap i Android, eller hvis det er vår egen eiendom, må vi spesifisere dens tilgangsmetoder, dvs. getter og setter-metoden.

Det samme kan implementeres ved bruk av XML som:

                /res/animator/object_animator_ex.xml

                        ---- Aktivitetskode ----

TextView animateTextView = (TextView) findViewById (R.id.tv_animate);

ObjectAnimator textViewAnimator = (ObjectAnimator) AnimatorInflater.loadAnimator (AnimationActivity.this, R.animator.object_animator_ex);
textViewAnimator.setTarget (animateTextView);
textViewAnimator.start ();

Gjør flere animasjoner om gangen

Vi kan ha flere ObjectAnimators til å starte samtidig og i samme varighet til å gjøre flere animasjoner, men det er ikke effektivt ettersom ingen visninger vet om noe annet syn. For å gjøre det samme kan vi bruke AnimatorSet-klassen.

I mitt nåværende prosjekt har jeg gjort følgende animasjon:

(Oppdateres snart. Beklager uleiligheten.)

Som vi ser er det flere animasjoner som kjører samtidig. Det er 4 samtidige animasjoner på gang. Når du klikker på søkeikonet, beveger først søkeikonet seg til venstre, logoen blekner, avbryt-knappen blekner og redigerer tekst.

Koden for å gjøre dette er:

   --------- utfør animasjon på søkeikonet klikk ----------
// ta til venstre plassering
DisplayMetrics displayMetrics = getResources (). GetDisplayMetrics ();
int modifierX = - (displayMetrics.widthPixels - v.getWidth ());
privat statisk endelig int SEARCH_ANIMATION_DURATION = 1000; // 1 sek
ObjectAnimator searchIconLeftAnimation = ObjectAnimator.ofFloat (v, "translationX", modifierX);
searchIconLeftAnimation.setDuration (SEARCH_ANIMATION_DURATION);

ObjectAnimator logoFadeOutAnimator = ObjectAnimator.ofFloat (mAppLogo, "alfa", 1f, 0f);
logoFadeOutAnimator.setDuration (SEARCH_ANIMATION_DURATION);

ObjectAnimator CancelImageFadeInAnimator = ObjectAnimator.ofFloat (mIvCancelSearch, "alpha", 0f, 1f);
cancelImageFadeInAnimator.setDuration (SEARCH_ANIMATION_DURATION);

ObjectAnimator searchEditTextAnimator = ObjectAnimator.ofFloat (mEtSearch, "alpha", 0f, 1f);
searchEditTextAnimator.setDuration (SEARCH_ANIMATION_DURATION);

AnimatorSet animatorSet = nytt AnimatorSet ();
animatorSet.play (searchIconLeftAnimation) .Med (logoFadeOutAnimator);
animatorSet.play (searchIconLeftAnimation) .Med (cancelImageFadeInAnimator);
animatorSet.play (searchIconLeftAnimation) .Med (searchEditTextAnimator);

animatorSet.start ();
   --------- reverser alle animasjonene ved avbryt klikk ----------
ObjectAnimator searchIconRightAnimation = ObjectAnimator.ofFloat (mIvSearch, "translationX", 0);
searchIconRightAnimation.setDuration (SEARCH_ANIMATION_DURATION);

ObjectAnimator logoFadeInAnimator = ObjectAnimator.ofFloat (mAppLogo, "alfa", 0f, 1f);
logoFadeInAnimator.setDuration (SEARCH_ANIMATION_DURATION);

ObjectAnimator cancelImageFadeOutAnimator = ObjectAnimator.ofFloat (mIvCancelSearch, "alpha", 1f, 0f);
cancelImageFadeOutAnimator.setDuration (SEARCH_ANIMATION_DURATION);

ObjectAnimator searchEditTextFadeInAnimator = ObjectAnimator.ofFloat (mEtSearch, "alpha", 1f, 0f);
searchEditTextFadeInAnimator.setDuration (SEARCH_ANIMATION_DURATION);

AnimatorSet animatorSet = nytt AnimatorSet ();
animatorSet.play (searchIconRightAnimation) .Med (logoFadeInAnimator);
animatorSet.play (searchIconRightAnimation) .Med (cancelImageFadeOutAnimator);
animatorSet.play (searchIconRightAnimation) .Med (searchEditTextFadeInAnimator);

animatorSet.start ();

Her har vi laget flere Object Animators på forskjellige visninger og spilt dem sammen ved hjelp av AnimatorSet. Metoder som lek () og med () er med på å oppnå dette.

Vi kan også bruke lyttere til å finne ut om animasjonsstatusen. For f.eks:

animatorSet.addListener (ny Animator.AnimatorListener () {
    @Overstyring
    public void onAnimationStart (Animator-animasjon) {
        // gjøre noe før animasjonen starter
    }

    @Overstyring
    public void onAnimationEnd (Animator-animasjon) {
       // gjøre andre ting etter at animasjonen er slutt
    }

    @Overstyring
    public void onAnimationCancel (Animator-animasjon) {
      // gjøre noe når animasjonen blir avbrutt (av bruker / utvikler)
    }

    @Overstyring
    public void onAnimationRepeat (Animator-animasjon) {
       // gjøre noe når animasjonen gjentar seg
    }
});

Når du utfører flere animasjoner i en enkelt visning

Til nå har vi sett animasjoner på forskjellige visningsobjekter. Vi kan utføre flere animasjoner på en enkelt visning ved å bruke de ovennevnte tilnærmingene (ved å bruke animatorsett), men det er en ytelse som det er prosesseringsoverhead for å sette opp AnimatorSet og kjøre to animatorer parallelt. En bedre tilnærming er å bruke ViewPropertyAnimator. Ved å bruke dette er koden enklere å lese også. For f.eks:

. AnimateTextView.animate () rotasjon (360f) .Y (500F) .setDuration (2000);
     ---------------------------- VS --------------------- --------
ObjectAnimator rotationAnimator = ObjectAnimator.ofFloat (animateTextView, "rotation", 360f);
rotationAnimator.setDuration (2000);
ObjectAnimator translateAnimator = ObjectAnimator.ofFloat (animateTextView, "translationY", 500f);
translateAnimator.setDuration (2000);
AnimatorSet set = new AnimatorSet ();
set.playTogether (rotationAnimator, translateAnimator);
set.start ();

Gjør animasjonen min treg, eller vil den overgå 16-timers vinduet tid? Er det noe overhead på forestillingen?

Animatører som oppdaterer brukergrensesnittet, gir ekstra gjengivelsesarbeid for hver ramme animasjonen kjører. Av denne grunn kan bruk av ressurskrevende animasjoner påvirke ytelsen til appen din negativt.

Arbeid som kreves for å animere brukergrensesnittet ditt legges til animasjonsfasen av gjengivelsesrørledningen. Du kan finne ut om animasjonene dine påvirker ytelsen til appen din ved å aktivere profil GPU-gjengivelse og overvåking av animasjonsfasen.

Tenk på brukssaken og bruk deretter riktig måte.

Takk for at du leser artikkelen. Forslag / rettelser / kommentarer er alltid velkomne. Hvis du liker det, kan du trykke på lignende-knappen og dele artikkelen med Android-fellesskapet. La oss dele kunnskapen så mye vi kan.

Merk - Del 2 på ViewAnimations kommer også ganske snart.

La oss også bli venner på About.me, Twitter, LinkedIn, Github og Facebook.