En begynderguide til implementering af Android-animationer - Del 1 (2 del serier)

Indrøm det, du har altid ønsket at oprette visuelt tiltalende apps. Men på grund af den første tilgang til funktionalitet blev animationer altid udsat. Ikke mere.

Lidt grundlæggende om animationer:

Der er 3 typer animationer:

  1. Egenskapsanimationer - De bruges til at ændre egenskab for objekter (Visninger eller objekter, der ikke er vist) Vi specificerer visse egenskaber (som translateX, TextScaleX) af de objekter, der skal ændres. Forskellige karakteristika ved animation, der kan manipuleres, er animationens varighed, hvorvidt den skal vendes, og hvor mange gange vi ønsker at gentage animationen osv. De blev introduceret i Android 3.0 (API-niveau 11).
  2. Se animationer - De bruges til at udføre enkle animationer som at ændre størrelse, placering, rotation, kontrollere gennemsigtighed. De er lette at opbygge og er meget hurtige, men har deres egne begrænsninger. For f.eks. - Deres tilstand ændres, men deres ejendom ændres ikke. Se animationer vil blive dækket i del 2.
  3. Tegnelige animationer - Dette bruges til at udføre animation vha. Tegnestoffer. Der laves en XML-fil, der specificerer forskellige liste over tegnestoffer, der køres en efter en, ligesom en rulle af en film. Dette er ikke meget brugt, så jeg vil ikke dække det.
Android 5.0 introducerede forskellige andre animationer - Reveal Effect, Activity / Fragment-overgange, Shared Element-overgange osv. Klik her for at lære mere om dette.
Bemærk - Del 1 vil kun diskutere egenskabsanimationer.

Hvornår skal du bruge hvilken type animation

  1. Hvis du bare ønsker at lave enkle animationer på visninger uden at skulle håndtere andre detaljer som berøring eller klik, skal du bruge Vis animationer. Problemet med View Animations er, at selvom View-tilstand ændres, forbliver dens egenskab stadig på den oprindelige position. Det betyder, at hvis en ImageButton flyttes fra 0 til 100 pixels til højre, selvom den animerer til højre, vil berøringen (egenskaben) af billedknappen stadig være på den 0. position.
  2. Se animationer kan bruges i stænkskærme. Når du bruger Vis animationer, skal du bruge XML i stedet for at gøre det programmatisk. Ved hjælp af XML-filer er den mere læsbar og kan deles mellem andre visninger.
  3. Hvis du vil håndtere berøring, skal du klikke på efter animationen, gå til egenskabsanimation, da de ændrer tilstand såvel som adfærd.

Egenskabsanimationskoncepter

Inde i ejendomsanimation. Med tilladelse fra Google.

Den aktuelle animation udføres af Value Animator. Denne klasse holder styr på animationens varighed og den aktuelle værdi af den egenskab, den animerer. TimeInterpolater holder øje med animationens tid (hastighed), som om det er med konstant hastighed på det givne tidspunkt, eller accelerer og derefter decelererer på det givne tidspunkt. TypeEvaluator bruges til at beregne fraktioner baseret på typen TypeEvalutor, der bruges til f.eks. Int, float, rgb osv. Vi kan bruge en brugerdefineret TypeEvaluator også, hvis ingen matcher vores behov.

Animationer ved hjælp af ValueAnimator

I klassen ValueAnimator kan du animere værdier af en eller anden type i en animations varighed ved at specificere et sæt int, float eller farveværdier, der skal animeres igennem. Du får en ValueAnimator ved at kalde en af ​​dens fabriksmetoder: 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 ()); // øg hastigheden først, og sænk derefter
valueAnimator.setDuration (2000);
valueAnimator.addUpdateListener (ny ValueAnimator.AnimatorUpdateListener () {
    @Override
    public void onAnimationUpdate (Animation af ValueAnimator) {
        float progress = (float) animation.getAnimatedValue ();
        animateTextView.setTranslationY (fremskridt);
        // ikke nødvendigt at bruge ugyldig (), da det allerede er til stede i // tekstvisningen.
    }
});
valueAnimator.start ();
Med tilladelse fra Giphy

Den samme ting kan opnås ved hjælp af 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 () {
    @Override
    public void onAnimationUpdate (Animation af ValueAnimator) {
        float progress = (float) animation.getAnimatedValue ();
        animateTextView.setTranslationY (fremskridt);
    }
});

valueAnimator.start ();

Animationer ved hjælp af ObjectAnimator

ObjectAnimator er en underklasse i ValueAnimator og kombinerer timingmotoren og værdeberegningen af ​​ValueAnimator med evnen til at animere en navngivet egenskab for et målobjekt. Dette gør animering af ethvert objekt meget lettere, da du ikke længere har brug for at implementere ValueAnimator.AnimatorUpdateListener, fordi den animerede egenskab opdateres automatisk. I de fleste tilfælde bør vi bruge dette.

For den samme animation ovenfor kan vi skrive koden til 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 kan se, behøvede vi ikke at bruge lytteren til at opdatere tekstvisningens placering, da dette gøres af ObjectAnimator selv. Det vigtigste her at se er “translationY”, som er den ejendom, vi vil udføre animation på. Dette skal være en defineret egenskab i Android, eller hvis det er vores egen egenskab, skal vi specificere dens accessor-metoder, dvs. getter og setter-metoden.

Den samme ting kan implementeres ved hjælp af 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 ();

Gør flere animationer ad gangen

Vi kan have flere ObjectAnimators til at starte på samme tid og i samme varighed til at udføre flere animationer, men det er ikke effektivt, da ingen visning ved noget andet synspunkt. For at gøre det samme kan vi bruge AnimatorSet-klassen.

I mit aktuelle projekt har jeg lavet følgende animation:

(Opdateres snart. Beklager ulejligheden.)

Som vi kan se, er der flere animationer, der kører på samme tid. Der foregår 4 samtidige animationer. Når der klikkes på søgeikonet, bevæger sig først søgeikonet til venstre, logoet falder ud, annulleringsknappen falder ind og redigering af tekst falder også ind. Ved at klikke på annulleringsknappen spilles den samme animation men omvendt.

Koden til at gøre dette er:

   --------- udfør animation på søgeikonet klik ----------
// tage til venstre position
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 = nyt AnimatorSet ();
animatorSet.play (searchIconLeftAnimation) .med (logoFadeOutAnimator);
animatorSet.play (searchIconLeftAnimation) .med (cancelImageFadeInAnimator);
animatorSet.play (searchIconLeftAnimation) .med (searchEditTextAnimator);

animatorSet.start ();
   --------- vende alle animationer ved annullering klik ----------
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 = nyt AnimatorSet ();
animatorSet.play (searchIconRightAnimation) .med (logoFadeInAnimator);
animatorSet.play (searchIconRightAnimation) .med (cancelImageFadeOutAnimator);
animatorSet.play (searchIconRightAnimation) .med (searchEditTextFadeInAnimator);

animatorSet.start ();

Her har vi oprettet flere Object Animators på forskellige visninger og spillet dem sammen ved hjælp af AnimatorSet. Metoder som play () og med () hjælper med at opnå dette.

Vi kan også bruge lyttere til at bestemme om animationsstatus. For f.eks:

animatorSet.addListener (ny Animator.AnimatorListener () {
    @Override
    public void onAnimationStart (Animator-animation) {
        // gør noget før animationen starter
    }

    @Override
    public void onAnimationEnd (Animator-animation) {
       // gøre andre ting, når animationen er afsluttet
    }

    @Override
    public void onAnimationCancel (Animator-animation) {
      // gøre noget, når animationen annulleres (af bruger / udvikler)
    }

    @Override
    public void onAnimationRepeat (Animator-animation) {
       // gør noget, når animationen gentager sig
    }
});

Når du udfører flere animationer på en enkelt visning

Indtil nu har vi set animationer på forskellige visningsobjekter. Vi kan udføre flere animationer på en enkelt visning ved hjælp af ovenstående fremgangsmåder også (ved hjælp af animatorsæt), men det er en præstationsomkostning, da der er behandlingsomkostningerne ved at opsætte AnimatorSet og køre to animatorer parallelt. En bedre tilgang er at bruge ViewPropertyAnimator. Ved hjælp af dette er koden også enklere at læse. For f.eks:

. AnimateTextView.animate () rotation (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 sæt = nyt AnimatorSet ();
set.playTogether (rotationAnimator, translateAnimator);
set.start ();

Gør animation min app langsom, eller overskrider den 16ms vindue tid? Er der noget overhead på forestillingen?

Animatører, der opdaterer brugergrænsefladen, medfører ekstra gengivelsesarbejde for hver ramme, hvor animationen kører. Af denne grund kan brug af ressourceintensive animationer have en negativ indflydelse på din apps ydelse.

Arbejd, der kræves for at animere dit brugergrænseflade, føjes til animationsstadiet i rendering pipeline. Du kan finde ud af, om dine animationer påvirker ydelsen af ​​din app ved at aktivere profil GPU-gengivelse og overvåge animationsfasen.

Tænk på brugssagen, og anvend derefter den rette måde.

Tak, fordi du læser artiklen. Forslag / rettelser / kommentarer er altid velkomne. Hvis du kan lide det, skal du trykke på lignende-knappen og dele artiklen med Android-samfundet. Lad os dele viden så meget som vi kan.

Bemærk - Del 2 på ViewAnimations kommer også meget snart.

Lad os også blive venner på About.me, Twitter, LinkedIn, Github og Facebook.