Pytanie Animacja Androida się nie powtórzy


Próbuję zrobić prostą animację, która będzie powtarzać się kilka razy (lub nieskończenie).
Wygląda na to że android:repeatCount nie działa!
Oto mój zasób animacji z /res/anim/first_animation.xml :

<?xml version="1.0" encoding="utf-8"?>
<set
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shareInterpolator="false"
    android:repeatCount="infinite"
    >
    <scale
        android:interpolator="@android:anim/decelerate_interpolator"
        android:duration="500"
        android:fromXScale="1.0"
        android:fromYScale="1.0"
        android:toXScale="1.2"
        android:toYScale="1.2"
        android:pivotX="50%"
        android:pivotY="50%"
        android:fillAfter="false" />
    <scale
        android:interpolator="@android:anim/accelerate_interpolator"
        android:startOffset="500"
        android:duration="500"
        android:fromXScale="1.2"
        android:fromYScale="1.2"
        android:toXScale="1.0"
        android:toYScale="1.0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:fillAfter="false" />
</set>

Najpierw powinien skalować obraz od 1,0 do 1,2 wielkości w 500 ms.
A następnie skalować go z powrotem do 1,0 w 500 ms.
Oto, jak go używam:

Animation firstAnimation = AnimationUtils.loadAnimation(this, R.anim.first_animation);
imgView.startAnimation(firstAnimation);

Wykonuje jeden cykl, a następnie kończy.
Skala się, następnie skaluje, a następnie zatrzymuje.

Jak mogę sprawić, aby działało zgodnie z zamierzeniami?


76
2017-12-18 23:04


pochodzenie


Co to jest imgView tutaj w twoim kodzie java? - clifgray


Odpowiedzi:


Aktualizacja: Jeszcze w wrześniu 2011 r. Inżynier Androida naprawił ten problem w większości przypadków. Atrybuty zignorowane w XML działają teraz, z wyjątkiem repeatCount i fillEnabled które są nadal ignorowane (celowo z jakiegoś powodu). Oznacza to, że nadal nie jest łatwo powtórzyć AnimationSet Niestety.

Aby uzyskać szczegółowe informacje, zobacz przegląd w zaktualizowane dokumenty (wyjaśnia, które atrybuty są ignorowane, które działają, a które przekazywane są na dzieci). I dla głębszego zrozumienia czego fillAfter, fillBefore, i fillEnabled tak naprawdę, zobacz post na blogu inżyniera (Chet Haase) tutaj.


Oryginalna odpowiedź

Aby rozwinąć odpowiedzi Pavela i innych: to prawda, że <set> tag jest śmiesznie zapluskwiony. Nie radzi sobie poprawnie z repeatCount i wiele innych atrybutów.

Spędziłem kilka godzin na zastanawianiu się nad tym, co może, a czego nie można załatwić, i przesłałem tutaj raport o błędzie / problem: Problem 17662

Podsumowując (dotyczy to AnimationSets):

setRepeatCount () / android: repeatCount

Ten atrybut (jak również repeatMode) nie działa w kodzie ani XML. Powoduje to, że powtarzanie całego zestawu animacji jest trudne.

setDuration () / android: duration

Ustawienie tego w AnimationSet w kodzie WORKS (nadpisuje wszystkie czasy animacji dla dzieci), ale nie w przypadku, gdy jest zawarte w tagu w XML

setFillAfter () / android: fillAfter

Działa to zarówno w kodzie, jak i w kodzie XML dla tagu. O dziwo, udało mi się to również zadziałać bez konieczności ustawiania fillEnabled na true.

setFillBefore () / android: fillBefore

Wydaje się, że nie ma żadnego efektu / ignorowany zarówno w kodzie, jak i w XML

setFillEnabled () / android: fillEnabled

Wydaje się, że nie ma żadnego efektu / zignorowany zarówno w kodzie, jak iw XML. Nadal mogę uzyskać fillAfter do pracy nawet bez uwzględnienia fillEnabled lub ustawienie fillEnabled na false.

setStartOffset () / android: startOffset

Działa to tylko w kodzie, a nie w XML.


62
2018-06-15 00:45





Znalazłem to <zestaw> tag ma implementację buggy w klasie AnimationSet.
Nie radzi sobie poprawnie z repeatCount.
Co możemy zrobić - to ustawić repeatCount bezpośrednio w <scale> etykietka.

Ten zasób XML działa dobrze:

<?xml version="1.0" encoding="utf-8"?>
<scale
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/accelerate_decelerate_interpolator"
    android:duration="200"
    android:fromXScale="1.0"
    android:fromYScale="1.0"
    android:toXScale="1.05"
    android:toYScale="1.05"
    android:pivotX="50%"
    android:pivotY="50%"
    android:repeatMode="reverse"
    android:fillAfter="false"
    android:repeatCount="24"
/>

Niestety jest to ograniczone tylko do jednej animacji na raz.
Nie możemy w ten sposób zdefiniować sekwencji animacji ...


41
2017-12-19 20:25



Używam 2 animacji w zestawie i nie dają mi żadnego problemu. uprzejmie powiedz mi o jakim problemie mówisz? który błąd? aktualnie pracuje nad 1.6 SDK - AZ_


Powinieneś dołączyć atrybut

android:repeatCount="infinite"

Ale w twojej "skali" animacji nie w "zestawie"


38
2018-01-30 17:48



ale czy te animacje czekają na zakończenie poprzedniej? dzięki - filthy_wizard
tak, pracuję dla mnie. - Ranjith Kumar
Dzięki, to zadziałało! Ustawienie programowe nie miało żadnego powodu. - cherry-wave
Dzięki! To zadziałało. Ale to jest ciągłe. Czy można to zrobić, powiedz co 5 sekund? - d34th4ck3r


Aby uzyskać powtarzalną animację, wykorzystałem program do słuchania animacji i ponownie wywołałem animację po jej zakończeniu. To robi siatkę kamer skupiającą się jak animacja z nawiasami.

Oto xml układu animacji

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale
    android:fromXScale="1.0"
    android:toXScale=".7"
    android:fromYScale="1.0"
    android:pivotX="50%"
    android:pivotY="50%"
    android:toYScale=".7"
    android:duration="1000"/>
<scale 
    android:duration="1000"
    android:fromXScale=".7"
    android:toXScale="1.0"
    android:fromYScale=".7"
    android:pivotX="50%"
    android:pivotY="50%"
    android:toYScale="1.0"
    android:startOffset="1000"/>

</set>

Oto kod Java

 public void startAnimation() {

            View brackets = findViewById(R.id.brackets);
            brackets.setVisibility(View.VISIBLE);

            Animation anim = AnimationUtils.loadAnimation(BuzzFinderActivity.this, R.anim.crosshair_focusing);
            anim.setAnimationListener(new AnimationListener() {

                @Override
                public void onAnimationEnd(Animation arg0) {
                    Animation anim = AnimationUtils.loadAnimation(BuzzFinderActivity.this, R.anim.crosshair_focusing);
                    anim.setAnimationListener(this);
                    brackets.startAnimation(anim);

                }

                @Override
                public void onAnimationRepeat(Animation arg0) {
                    // TODO Auto-generated method stub

                }

                @Override
                public void onAnimationStart(Animation arg0) {
                    // TODO Auto-generated method stub

                }

            });


            brackets.startAnimation(anim);
}

30
2018-02-24 00:31



To powinna być poprawna odpowiedź. - Adam Varhegyi
Tak, powinna to być poprawna odpowiedź. Działa na wszystkich urządzeniach i poziomie systemu operacyjnego - Smeet
pomógł mi również, ale usunąłem te dwie linie z metody End Animation anim = AnimationUtils.loadAnimation (BuzzFinderActivity.this, R.anim.crosshair_focusing); anim.setAnimationListener (this); - aida


Miałem też ten sam problem ... włączyłem android: repeatCount = "infinite" w pliku XMl. działa dobrze ...

  <translate 
           android:fromXDelta="0"
           android:toXDelta="80"
           android:duration="1000"
           android:repeatCount="infinite"   
           android:repeatMode="reverse" 
           android:pivotX="50%"
           android:pivotY="50%"                             
           android:fillAfter="true"/>

 


10
2018-05-24 10:28





możesz spróbować tego kodu. W swoim kodzie po prostu dodaj,

firstAnimation.setRepeatCount(5);

Spowoduje to powtórzenie animacji na określony czas

firstAnimation.setRepeatCount(Animation.INFINITE);
firstAnimation.setRepeatMode(Animation.INFINITE);

Powtarza to animację w nieskończoność.


9
2017-12-30 04:17



repeatModepowinien być albo RESTART lub REVERSE - xinthink
dokładnie to, co chcę, ustawić dynamicznie na nieskończoność. - Varun Chaudhary
setRepeat nie działa zgodnie z code.google.com/p/android/issues/detail?id=17662 - ElliotM


Próbowałem użyć kodu Daniela do pokazania animacji dokładnie tyle razy i miałem problem: animacja była pokazywana w przybliżeniu n / 2 razy, gdy oczekiwano n razy.

Więc zmodyfikowałem kod Daniela:

//...
@Override
public void onAnimationEnd(Animation arg0) {
    mCurrentCount++;
    if (mCurrentCount < REPEAT_COUNT) {  
        Animation anim = AnimationUtils.loadAnimation(BuzzFinderActivity.this, R.anim.crosshair_focusing);
        anim.setAnimationListener(this);
        brackets.post(new Runnable() {
            @Override
            public void run() {
                brackets.startAnimation(anim);
            }
        }  
    } 
}
//... 

Używając wariantu pokazanego powyżej, animacja jest pokazywana tylko REPEAT_COUNT razy, ponieważ metoda View.post () daje możliwość uruchomienia nowej animacji po zakończeniu wszystkich akcji, związanych z poprzednią animacją.


2
2017-12-28 04:48





Z Androidem SDK w wersji 4.0.3:

W podanych elementach animacji:

android: repeatCount = "- 1"

sprawia, że ​​jest to nieskończona animacja.


2
2018-01-11 08:49



Dzięki! Działa dobrze na 4.2 bez obejścia - ruX


Dodaj następującą klasę do swojego projektu:

import android.view.View;
import android.view.animation.Animation;

public class AnimationRepeater implements Animation.AnimationListener
{
    private View view;
    private Animation animation;
    private int count;

    public AnimationRepeater(View view, Animation animation)
    {
        this.view = view;
        this.animation = animation;
        this.count = -1;
    }

    public AnimationRepeater(View view, Animation animation, int count)
    {
        this.view = view;
        this.animation = animation;
        this.count = count;
    }

    public void start()
    {
        this.view.startAnimation(this.animation);
        this.animation.setAnimationListener(this);
    }

    @Override
    public void onAnimationStart(Animation animation) { }

    @Override
    public void onAnimationEnd(Animation animation)
    {
        if (this.count == -1)
            this.view.startAnimation(animation);
        else
        {
            if (count - 1 >= 0)
            {
                this.animation.start();
                count --;
            }
        }
    }

    @Override
    public void onAnimationRepeat(Animation animation) { }
}

Aby uzyskać nieskończoną pętlę widoku, wykonaj następujące czynności:

Animation a = AnimationUtils(Context, R.anim.animation);
new AnimationRepeater(View, a).start();

Jeśli chcesz powtórzyć animację tylko dla N-razy, wykonaj następujące czynności:

Animation a = AnimationUtils(Context, R.anim.animation);
new AnimationRepeater(View, a, int N).start();

N oznacza liczbę powtórzeń.


2
2017-08-19 13:53





Większość moich rzeczy robię programowo i mogę być spóźniona lub nieskuteczna w tym przypadku, ale dokończyłem cel powtarzania animacji (mam nawet 2 naprzemienne zestawy animacji). Cały ten kod to po prostu zanikanie w jednym obrazie, pauza, potem wyciemnienie, zanikanie w innym obrazie, pauza, zanikanie i przywracanie pierwszego obrazu (płukanie i powtarzanie). Po raz pierwszy zdefiniowałem moje Imageviews:

    final ImageView purple = (ImageView)findViewById(R.id.purp);
    final ImageView yellow = (ImageView)findViewById(R.id.yell);
    purple.setVisibility(View.INVISIBLE);
    yellow.setVisibility(View.INVISIBLE);

Następnie stworzyłem dwa liczniki czasu, timery zadań i procedury obsługi, aby poradzić sobie z momentem rozpoczęcia i zatrzymania każdej animacji:

    Timer p = new Timer();
    TimerTask pu = new TimerTask() {
        public void run() {
                handler1.post(new Runnable() {
                        public void run() 
                        {
                           fadein(purple);
                        }
               });
        }};
        p.schedule(pu, 6000, 12000);

    final Handler handler2 = new Handler();

    Timer y = new Timer();
    TimerTask ye = new TimerTask() {
        public void run() {
                handler2.post(new Runnable() {
                        public void run() 
                        {
                           fadein(yellow);
                        }
               });
        }};

        y.schedule(ye, 0, 12000);

Na koniec, zamiast tworzyć zestawy animacji dodając animacje, po prostu słucham animacji, aby określić, kiedy rozpocząć każdą animację:

public void fadein (final ImageView image)
{
    Animation anim = new AlphaAnimation(0, 1);

    anim.setDuration(2000);

    image.startAnimation(anim);
    anim.setAnimationListener(new AnimationListener() {
        public void onAnimationEnd(Animation animation) 
        {
            image.clearAnimation();
            image.invalidate();
            pause(image);

        }

        @Override
        public void onAnimationRepeat(Animation animation) {
            // TODO Auto-generated method stub

        }

        @Override
        public void onAnimationStart(Animation animation) {
            // TODO Auto-generated method stub

        }
    });
}    
public void pause (final ImageView image)
{
    Animation anim = new AlphaAnimation(1, 1);

    anim.setDuration(2000);

    image.startAnimation(anim);
    anim.setAnimationListener(new AnimationListener() {
        public void onAnimationEnd(Animation animation) 
        {
            image.clearAnimation();
            image.invalidate();
            fadeout(image);

        }

        @Override
        public void onAnimationRepeat(Animation animation) {
            // TODO Auto-generated method stub

        }

        @Override
        public void onAnimationStart(Animation animation) {
            // TODO Auto-generated method stub

        }
    });
}     
public void fadeout (final ImageView image)
{
    Animation anim = new AlphaAnimation(1,0);

    anim.setDuration(2000);

    image.startAnimation(anim);
    anim.setAnimationListener(new AnimationListener() {
        public void onAnimationEnd(Animation animation) 
        {
            image.clearAnimation();
            image.invalidate();
        }

        @Override
        public void onAnimationRepeat(Animation animation) {
            // TODO Auto-generated method stub

        }

        @Override
        public void onAnimationStart(Animation animation) {
            // TODO Auto-generated method stub

        }
    });
}    

Wyraźne zrozumienie i unieważnienie, gdzie tylko poprzednie próby i poprawne działanie tej rzeczy. Nie wiem, czy są one wymagane, czy nie.

Mam nadzieję, że to pomaga komuś.


Ryan


1
2017-12-14 14:41