Een beginnersgids voor het implementeren van Android-animaties - Deel 1 (2 deelreeksen)

Geef toe, je hebt altijd al visueel aantrekkelijke apps willen maken. Maar vanwege functionaliteit eerste aanpak, waren animaties altijd uitgesteld. Niet meer.

Een paar basisprincipes over animaties:

Er zijn 3 soorten animaties:

  1. Eigenschapanimaties - Ze worden gebruikt om de eigenschap van objecten te wijzigen (weergaven of niet-weergaveobjecten). We specificeren bepaalde eigenschappen (zoals translateX, TextScaleX) van de te wijzigen objecten. Verschillende karakteristieken van animatie die kunnen worden gemanipuleerd zijn animatieduur, of deze moet worden omgekeerd en hoe vaak we de animatie willen herhalen, enz. Ze werden geïntroduceerd in Android 3.0 (API level 11).
  2. Bekijk animaties - Ze worden gebruikt om eenvoudige animaties te maken, zoals het veranderen van grootte, positie, rotatie, controle transparantie. Ze zijn eenvoudig te bouwen en zijn erg snel, maar hebben hun eigen beperkingen. Voor bijvoorbeeld - Hun staat verandert maar hun eigendom verandert niet. Animaties bekijken wordt behandeld in deel 2.
  3. Drawable Animations - Dit wordt gebruikt om animatie te maken met behulp van drawables. Er wordt een XML-bestand gemaakt met verschillende lijst met tekentabellen die één voor één worden uitgevoerd, net als een filmrol. Dit wordt niet veel gebruikt, dus ik zal het niet behandelen.
Android 5.0 introduceerde verschillende andere animaties - Onthuleffect, activiteit / fragmentovergangen, gedeelde elementovergangen enz. Klik hier voor meer informatie.
Opmerking - Deel 1 bespreekt alleen Property-animaties.

Wanneer welk type animatie te gebruiken

  1. Als u alleen eenvoudige animaties in weergaven wilt maken zonder andere details zoals aanraken of klikken te hoeven verwerken, gebruikt u Animaties bekijken. Het probleem met View Animations is dat, hoewel de View-status verandert, de eigenschap nog steeds op de oorspronkelijke positie blijft. Dat betekent dat als een ImageButton van 0 naar 100 pixels naar rechts wordt verplaatst, hoewel deze naar rechts zal animeren, de aanraking (eigenschap) van de afbeeldingsknop zich nog steeds op de 0e positie bevindt.
  2. Beeldanimaties kunnen worden gebruikt in Splash-schermen. Gebruik bij weergave-animaties XML in plaats van programmatisch te doen. Met behulp van XML-bestanden is het beter leesbaar en kan het worden gedeeld met andere weergaven.
  3. Als u de aanraking wilt verwerken, klikt u na de animatie, kiest u voor Eigenschapanimatie omdat deze de status en het gedrag verandert.

Eigenschap animatie concepten

Binnenkant van animatie van onroerend goed. Met dank aan Google.

De eigenlijke animatie wordt gedaan door Value Animator. Deze klasse houdt de animatieduur bij en de huidige waarde van de eigenschap die wordt geanimeerd. TimeInterpolater houdt de tijd (snelheid) van de animatie bij, zoals of deze met een constante snelheid is in de gegeven tijd, of versnelt en vervolgens vertraagt ​​in de gegeven tijd. TypeEvaluator wordt gebruikt om breuken te berekenen op basis van het type TypeEvalutor dat wordt gebruikt voor bijvoorbeeld int, float, rgb enz. We kunnen een aangepaste TypeEvaluator ook gebruiken als deze niet aan onze behoeften voldoet.

Animaties met ValueAnimator

Met de klasse ValueAnimator kunt u waarden van een bepaald type animeren voor de duur van een animatie door een reeks int-, float- of kleurwaarden op te geven om doorheen te animeren. U verkrijgt een ValueAnimator door een van de fabrieksmethoden aan te roepen: ofInt (), ofFloat () of ofObject (). Bijvoorbeeld:

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

ValueAnimator valueAnimator = ValueAnimator.ofFloat (0f, 500f);
valueAnimator.setInterpolator (nieuwe AccelerateDecelerateInterpolator ()); // verhoog eerst de snelheid en verlaag vervolgens
valueAnimator.setDuration (2000);
valueAnimator.addUpdateListener (nieuwe ValueAnimator.AnimatorUpdateListener () {
    @ Override
    public void onAnimationUpdate (ValueAnimator-animatie) {
        float progress = (float) animation.getAnimatedValue ();
        animateTextView.setTranslationY (vooruitgang);
        // niet nodig om invalidate () te gebruiken, omdat het al aanwezig is in // de tekstweergave.
    }
});
valueAnimator.start ();
Met dank aan Giphy

Hetzelfde kan als volgt worden bereikt met behulp van XML-code:

                   /res/animator/value_animator_ex.xml

                     ---- Activiteitscode ----
ValueAnimator valueAnimator = (ValueAnimator) AnimatorInflater.loadAnimator (
        dit, R.animator.value_animator_ex);

valueAnimator.addUpdateListener (nieuwe ValueAnimator.AnimatorUpdateListener () {
    @ Override
    public void onAnimationUpdate (ValueAnimator-animatie) {
        float progress = (float) animation.getAnimatedValue ();
        animateTextView.setTranslationY (vooruitgang);
    }
});

valueAnimator.start ();

Animaties met ObjectAnimator

De ObjectAnimator is een subklasse van de ValueAnimator en combineert de timing-engine en de waardeberekening van ValueAnimator met de mogelijkheid om een ​​benoemde eigenschap van een doelobject te animeren. Dit maakt het animeren van elk object veel eenvoudiger, omdat u de ValueAnimator.AnimatorUpdateListener niet langer hoeft te implementeren, omdat de geanimeerde eigenschap automatisch wordt bijgewerkt. In de meeste gevallen moeten we dit gebruiken.

Voor dezelfde animatie hierboven kunnen we de code voor ObjectAnimator schrijven als:

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

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

Zoals we kunnen zien, hoefden we de luisteraar niet te gebruiken om de positie van de tekstweergave bij te werken, omdat dit door ObjectAnimator zelf wordt gedaan. Het belangrijkste hier om te zien is "translationY", het eigendom waarop we animatie willen uitvoeren. Dit moet een gedefinieerde eigenschap in Android zijn of als het onze eigen eigenschap is, moeten we de accessormethoden opgeven, d.w.z. getter en setter-methode.

Hetzelfde kan worden geïmplementeerd met XML als:

                /res/animator/object_animator_ex.xml

                        ---- Activiteitscode ----

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 ();

Meerdere animaties tegelijk uitvoeren

We kunnen meerdere ObjectAnimators tegelijkertijd en voor dezelfde duur laten starten om meerdere animaties te maken, maar het is niet efficiënt omdat geen enkele weergave weet van een andere weergave. Om hetzelfde te doen, kunnen we de klasse AnimatorSet gebruiken.

In mijn huidige project heb ik de volgende animatie uitgevoerd:

(Wordt binnenkort bijgewerkt. Sorry voor het ongemak.)

Zoals we kunnen zien, zijn er meerdere animaties tegelijkertijd actief. Er zijn 4 gelijktijdige animaties aan de gang. Wanneer op het zoekpictogram wordt geklikt, wordt eerst het zoekpictogram naar links verplaatst, het logo vervaagt, de knop Annuleren verdwijnt en tekst wordt ook zichtbaar. Als u op de knop Annuleren klikt, wordt dezelfde animatie afgespeeld, maar omgekeerd.

De code om dit te doen is:

   --------- animatie uitvoeren bij klikken op zoekpictogram ----------
// breng naar de meest linkse positie
DisplayMetrics displayMetrics = getResources (). GetDisplayMetrics ();
int modifierX = - (displayMetrics.widthPixels - v.getWidth ());
private statische finale int SEARCH_ANIMATION_DURATION = 1000; // 1 seconde
ObjectAnimator searchIconLeftAnimation = ObjectAnimator.ofFloat (v, "translationX", modifierX);
searchIconLeftAnimation.setDuration (SEARCH_ANIMATION_DURATION);

ObjectAnimator logoFadeOutAnimator = ObjectAnimator.ofFloat (mAppLogo, "alpha", 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 = nieuw AnimatorSet ();
animatorSet.play (searchIconLeftAnimation) .met (logoFadeOutAnimator);
animatorSet.play (searchIconLeftAnimation) .met (cancelImageFadeInAnimator);
animatorSet.play (searchIconLeftAnimation) .met (searchEditTextAnimator);

animatorSet.start ();
   --------- alle animaties omkeren bij annuleren klik ----------
ObjectAnimator searchIconRightAnimation = ObjectAnimator.ofFloat (mIvSearch, "translationX", 0);
searchIconRightAnimation.setDuration (SEARCH_ANIMATION_DURATION);

ObjectAnimator logoFadeInAnimator = ObjectAnimator.ofFloat (mAppLogo, "alpha", 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 = nieuw AnimatorSet ();
animatorSet.play (searchIconRightAnimation) .met (logoFadeInAnimator);
animatorSet.play (searchIconRightAnimation) .met (cancelImageFadeOutAnimator);
animatorSet.play (searchIconRightAnimation) .met (searchEditTextFadeInAnimator);

animatorSet.start ();

Hier hebben we meerdere objectanimators in verschillende weergaven gemaakt en ze samen gespeeld met AnimatorSet. Methoden zoals play () en with () helpen dit te bereiken.

We kunnen ook luisteraars gebruiken om de animatiestatus te bepalen. Voor bijvoorbeeld:

animatorSet.addListener (nieuwe Animator.AnimatorListener () {
    @ Override
    openbare nietig op onAnimationStart (Animator-animatie) {
        // doe alles voordat de animatie begint
    }

    @ Override
    public void onAnimationEnd (Animator-animatie) {
       // doe andere dingen nadat de animatie is afgelopen
    }

    @ Override
    openbare nietig op onAnimationCancel (Animator-animatie) {
      // iets doen wanneer animatie wordt geannuleerd (door gebruiker / ontwikkelaar)
    }

    @ Override
    openbare nietig op onAnimationRepeat (Animator-animatie) {
       // doe iets wanneer de animatie zich herhaalt
    }
});

Bij het uitvoeren van meerdere animaties in één weergave

Tot nu toe hebben we animaties op verschillende weergaveobjecten gezien. We kunnen meerdere animaties uitvoeren op een enkele weergave met behulp van de bovenstaande benaderingen ook (met behulp van animatorset), maar het is een prestatieoverhead omdat er de verwerkingsoverhead is van het instellen van de AnimatorSet en het gelijktijdig uitvoeren van twee Animators. Een betere aanpak is om ViewPropertyAnimator te gebruiken. Hiermee is de code ook eenvoudiger te lezen. Voor bijvoorbeeld:

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

Maakt animatie mijn app traag of overtreft deze de 16ms tekenvenster tijd? Is er enige overhead op de uitvoering?

Animators die de gebruikersinterface bijwerken, zorgen voor extra rendering voor elk frame waarin de animatie wordt uitgevoerd. Om deze reden kan het gebruik van intensieve animaties de prestaties van uw app negatief beïnvloeden.

Het vereiste werk om uw gebruikersinterface te animeren, wordt toegevoegd aan de animatiefase van de renderingpijplijn. U kunt achterhalen of uw animaties de prestaties van uw app beïnvloeden door Profile GPU Rendering in te schakelen en de animatiefase te bewaken.

Denk na over de use case en pas dan de juiste manier toe.

Bedankt voor het lezen van het artikel. Suggesties / correcties / opmerkingen zijn altijd welkom. Als het je bevalt, klik je op de knop Vind ik leuk en deel je het artikel met de Android-community. Laten we de kennis zoveel mogelijk delen.

Opmerking - Deel 2 over ViewAnimations komt ook zeer binnenkort.

Laten we ook vrienden worden op About.me, Twitter, LinkedIn, Github en Facebook.