Андроидная анимация не повторяется

Я пытаюсь сделать простую анимацию, которая повторяется несколько раз (или бесконечно).
Кажется, что android:repeatCount не работает!
Вот мой ресурс анимации из /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> 

Сначала он должен масштабировать изображение размером от 1,0 до 1,2 в 500 мс.
А затем масштабируйте его до 1,0 в 500 мс.
Вот как я его использую:

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

Он делает один цикл, а затем заканчивается.
Он масштабируется, затем масштабируется и затем останавливается.

Как я могу сделать эту работу по назначению?

Обновление: в сентябре 2011 года разработчик Android исправил эту проблему по большей части. Атрибуты, которые были проигнорированы в XML, теперь работают, за исключением repeatCount и fillEnabled которые по-прежнему игнорируются (по какой-то причине). Это означает, что пока нелегко повторить AnimationSet .

Подробнее см. Обзор в обновленных документах (объясняет, какие атрибуты игнорируются, какие работают и которые передаются детям). И для более глубокого понимания того, что fillAfter , fillBefore и fillEnabled самом деле, см. Здесь сообщение блога инженера (Chet Haase).


Оригинальный ответ

Расширить ответы Павла и других: правда, <set> смехотворно глючит. Он не может правильно repeatCount и ряд других атрибутов.

Я потратил несколько часов на то, чтобы выяснить, что он может и не может решить, и представил здесь отчет об ошибке / проблеме: Issue 17662

В целом (это касается AnimationSet s):

SetRepeatCount () / android: repeatCount

Этот атрибут (а также repeatMode) не работает в коде или XML. Это затрудняет повторение всего набора анимаций.

SetDuration () / android: продолжительность

Установка этого в AnimationSet в коде WORKS (отменяет все длительности анимаций для детей), но не при включении в тег в XML

SetFillAfter () / android: fillAfter

Это работает как в коде, так и в XML для тега. Как ни странно, я получил его и работать без необходимости устанавливать fillEnabled в true.

SetFillBefore () / android: fillBefore

Кажется, не имеет никакого эффекта / игнорируется как в коде, так и в XML

SetFillEnabled () / android: fillEnabled

Кажется, не имеет никакого эффекта / игнорируется как в коде, так и в XML. Я все еще могу получить fillAfter, чтобы работать даже без включения fillEnabled или установки fillEnabled на false.

SetStartOffset () / android: startOffset

Это работает только в коде, а не в XML.

Я обнаружил, что тег <set> имеет ошибку с ошибкой в ​​классе AnimationSet .
Он не может правильно обрабатывать repeatCount .
Что мы можем сделать – это установить repeatCount непосредственно в теге <scale> .

Этот XML-ресурс работает хорошо:

 <?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" /> 

К сожалению, это ограничивается только одной анимацией сразу.
Мы не можем определить последовательность анимаций таким образом …

Вы должны включить атрибут

 android:repeatCount="infinite" 

Но в вашей «масштабной» анимации не в «наборе»,

Чтобы получить повторяющуюся анимацию, я использовал прослушиватель анимации и снова вызвал анимацию, когда она закончилась. Это делает ретикулу камеры, фокусируясь как анимация с помощью скобок.

Вот макет анимации xml

 <?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> 

Вот код 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); } 

Вы можете попробовать этот код. В вашем коде просто добавьте,

 firstAnimation.setRepeatCount(5); 

Это повторит анимацию в течение определенного времени

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

Это повторит анимацию на неопределенный срок.

Я также столкнулся с той же проблемой .. я включил android: repeatCount = «бесконечный» в файле XMl.

  <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"/> 

Я попытался использовать код Дэниела, чтобы показать анимацию точное количество раз и возникла проблема: анимация была показана приблизительно, n / 2 раза, когда n раз ожидалось.

Поэтому я изменил код Дэниела:

 //... @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); } } } } //... 

Используя вариант, показанный выше, анимация отображается exectly REPEAT_COUNT раз, потому что метод View.post () дает возможность запускать новую анимацию после завершения всех действий, связанных с предыдущей анимацией.

С android sdk версия 4.0.3:

В данных анимационных элементах:

андроид: RepeatCount = "- 1"

Делает его бесконечной анимацией.

Добавьте в свой проект следующий класс:

 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) { } } 

Для бесконечного цикла вашего представления сделайте следующее:

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

Если вы хотите повторить анимацию только за N раз, сделайте следующее:

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

N обозначает количество повторений.

Я делаю большую часть своих программных продуктов, и я могу опаздывать или неэффективно в этом, но это, но я выполнил цель повторного анимации (у меня даже есть 2 чередующихся набора анимации). Весь этот код просто исчезает в одном изображении, приостанавливается, затем исчезает, исчезает в другом изображении, приостанавливается, исчезает и возвращает первый (полоскание и повторение). Сначала я определил свои изображения:

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

Затем я сделал два таймера, таймеры задач и обработчики, чтобы разобраться, когда начинать и останавливать каждую анимацию:

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

Наконец, вместо создания наборов анимаций, добавляя анимацию, я просто слушаю анимацию, чтобы определить, когда начинать каждую анимацию:

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

Прояснение и недействительность, когда только предыдущие попытки и правильное использование этой вещи. Я не знаю, нужны они или нет.

Надеюсь, это поможет кому-то.


Райан

Я получил это, чтобы пойти … я пытался получить представление, чтобы вращаться по кругу непрерывно.

Предыдущий я использовал rotation.setRepeatMode (-1), но это не сработало. Переключился на setrepeatcount, и он работает. Это на желеобразной фасоли 4.2.2

  ObjectAnimator rotation = ObjectAnimator.ofFloat(myview, "rotation", 360).setDuration(2000); rotation.setRepeatMode(-1); rotation.setRepeatCount(Animation.INFINITE); rotation.start(); 

Попробуйте добавить код в поток цикла или while / for statement

Я столкнулся с той же проблемой, но не хотел делать какие-либо события времени на Java из-за того, что поток пользовательского интерфейса иногда может быть очень занят. Флаг INFINITE не работает для установленного тега. Поэтому я решил проблему с небольшим фрагментом кода:

 mAnimation = (AnimationSet) AnimationUtils.loadAnimation(myContext, R.anim.blink); mIcon.startAnimation(mAnimation); mAnimation.setAnimationListener(new AnimationListener() { public void onAnimationStart(Animation animation) {} public void onAnimationRepeat(Animation animation) {} public void onAnimationEnd(Animation animation) { mIcon.startAnimation(mAnimation); } }); 

Со следующим XML:

 <alpha xmlns:android="http://schemas.android.com/apk/res/android" android:duration="1000" android:fromAlpha="0.0" android:toAlpha="1.0" /> <alpha xmlns:android="http://schemas.android.com/apk/res/android" android:duration="1000" android:fromAlpha="0.9" android:startOffset="1000" android:toAlpha="0.0" /> 

Где mIcon является ImageView из моего макета.

Я решил эту проблему. Это моя версия исправления:

 public class HelloAndroidActivity extends Activity { private static String TAG = "animTest"; private Animation scaleAnimation; private int currentCover = 0; private List<ImageView> imageViews = new ArrayList<ImageView>(3); private Button btn; private ImageView img; /** * Called when the activity is first created. * @param savedInstanceState If the activity is being re-initialized after * previously being shut down then this Bundle contains the data it most * recently supplied in onSaveInstanceState(Bundle). <b>Note: Otherwise it is null.</b> */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.i(TAG, "onCreate"); setContentView(R.layout.test); img = (ImageView)findViewById(R.id.testpict); imageViews.add(img); img = (ImageView)findViewById(R.id.testpictTwo); imageViews.add(img); img = (ImageView)findViewById(R.id.testpict3); imageViews.add(img); scaleAnimation = AnimationUtils.loadAnimation(this, R.anim.photo_scale); scaleAnimation.setAnimationListener(new CyclicAnimationListener()); btn = (Button)findViewById(R.id.startBtn); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { imageViews.get(0).startAnimation(scaleAnimation); } }); } private class CyclicAnimationListener implements AnimationListener{ @Override public void onAnimationEnd(Animation animation) { currentCover += 1; if(currentCover >= imageViews.size()){ currentCover = 0; } img = imageViews.get(currentCover); scaleAnimation = AnimationUtils.loadAnimation(HelloAndroidActivity.this, R.anim.photo_scale); scaleAnimation.setAnimationListener(new CyclicAnimationListener()); img.startAnimation(scaleAnimation); } @Override public void onAnimationRepeat(Animation animation) { Log.d("Animation", "Repeat"); } @Override public void onAnimationStart(Animation animation) { } } } 

Я просто столкнулся с этой проблемой, работая над обратным совместимым приложением. Так расстраивает! Я закончил кодирование хорошего класса обходного пути, который можно вызывать из onCreate и будет запускать любой ресурс анимации в неопределенный цикл.

Класс, AnimationLooper, доступен здесь: https://gist.github.com/2018678

Изучив ответы из Интернета, я нашел решения, которые отлично подходят для меня. (И да, repeatCount и repeatMode чрезвычайно искажены при использовании вместе с animationSet).

anim_rotate_fade.xml:

 <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/accelerate_decelerate_interpolator" android:ordering="together" > <objectAnimator android:duration="3000" android:propertyName="rotation" android:repeatCount="1" android:valueTo="360" android:valueType="floatType" /> <objectAnimator android:duration="3000" android:propertyName="alpha" android:repeatCount="1" android:repeatMode="reverse" android:valueFrom="0.0" android:valueTo="0.3" android:valueType="floatType" /> <objectAnimator android:duration="3000" android:propertyName="y" android:repeatCount="1" android:repeatMode="reverse" android:valueFrom="380" android:valueTo="430" android:valueType="floatType" /> </set> 

В действии: (Решите это, введя небольшую задержку после окончания анимации).

 ImageView starlightImageView = new ImageView(this); starlightImageView.setImageResource(R.drawable.starlight); final AnimatorSet animate = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.anim.anim_rotate_fade); AnimatorListenerAdapter animatorListener = new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); new Handler().postDelayed(new Runnable() { @Override public void run() { animate.start(); } }, 1000); } }; animate.setTarget(starlightImageView); animate.addListener(animatorListener); 

Есть много классов, которые вы хотели бы исследовать, но в настоящее время я использую objectAnimator, который является очень гибким. Я бы не рекомендовал использовать Animation или AnimationUtils:

  • Анимация
  • AnimationUtils
  • мультипликатор
  • AnimatorInflater
  • AnimatorListener
  • AnimatorListenerAdapter

Нужно прислушаться к завершению первой анимации, а затем заново запустить анимацию в обратном вызове onStopAnimation, попробуйте эту ссылку

Маленькая настройка для @Danufr ответит, чтобы снова сохранить ресурсы при загрузке.

  operator = (ImageView) findViewById(R.id.operator_loading); final Animation ani = AnimationUtils.loadAnimation(getApplicationContext(),R.anim.finding_operator); ani.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { operator.startAnimation(ani); } @Override public void onAnimationRepeat(Animation animation) { } }); operator.setAnimation(ani); 

Я решил эту проблему, используя обратное в моем проекте.

<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:repeatMode="reverse" android:repeatCount="infinite" />

Я решил эту проблему, используя thread.

 Button btn = (Button) findViewById(R.id.buttonpush); final TextView textview = (TextView) findViewById(R.id.hello); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { textview.setText("..................."); final Animation animationtest = AnimationUtils.loadAnimation(MainActivity.this, android.R.anim.slide_in_left); animationtest.setDuration(1000); final Handler handler = new Handler(); Runnable runnable = new Runnable() { public void run() { handler.postDelayed(this, 1500); textview.startAnimation(animationtest); } }; handler.postDelayed(runnable, 500); // start handler.removeCallbacks(runnable); //STOP Timer } }); 

Он отлично работает

  GifDrawable gifDrawable = (GifDrawable) gifImageView.getDrawable(); gifDrawable.setLoopCount(0); 

Ни одно из вышеперечисленных решений не работало в моем случае. Решение Danuofr действительно работало для набора анимации, но когда я делал модульное тестирование, мои тесты использовались для застревания в этом бесконечном цикле. Наконец, для моего случая, мне нужно было повторить эту анимацию определенное количество раз. Итак, я вручную добавил копии анимации в anim_rot.xml в каскадном порядке, добавив значение смещения . Я знаю, что это плохо и не будет работать для многих, но это был единственный обходной путь для моего дела.

anim_rot.xml

 <set xmlns:android="http://schemas.android.com/apk/res/android"> <rotate android:duration="2000" android:fromDegrees="20" android:pivotX="29%" android:pivotY="50%" android:toDegrees="-20" /> <rotate android:duration="2000" android:fromDegrees="-20" android:pivotX="29%" android:pivotY="53%" android:startOffset="2000" android:toDegrees="20" /> <rotate android:startOffset="4000" android:duration="2000" android:fromDegrees="20" android:pivotX="29%" android:pivotY="56%" android:toDegrees="-20" /> <rotate android:duration="2000" android:fromDegrees="-20" android:pivotX="29%" android:pivotY="59%" android:startOffset="6000" android:toDegrees="20" /> <rotate android:startOffset="8000" android:duration="2000" android:fromDegrees="20" android:pivotX="29%" android:pivotY="62%" android:toDegrees="-20" /> <rotate android:duration="2000" android:fromDegrees="-20" android:pivotX="29%" android:pivotY="65%" android:startOffset="10000" android:toDegrees="20" /> </set> 

Я сделал это, чтобы повторить анимацию 3 раза. Вы можете добавить больше копий, чтобы повторить определенное время, добавив значения смещения.

Intereting Posts
Как найти самые близкие места на основе текущего lat и long с использованием Parse API (parse.com) в android Дешевый Android 7-дюймовый планшет (800×480): неправильное соотношение сторон, круги выглядят как многоточие Как использовать loopJ SyncHttpClient для синхронных вызовов? IInAppBillingService.aidl не может генерировать Java-файл в Android Studio В чем разница между android.R.layout.simple_list_item_1 и android.R.layout.simple_list_item_2 Android dev время против времени iPhone dev Исключение исключающего указателя Java Android: сообщение Http с параметрами не работает DownloadManager – получен ACTION_DOWNLOAD_COMPLETE, но статус STATUS_RUNNING Что произойдет, если return false в OnCreate ContentProvider? Эмулятор Android не использует файл хоста Windows? Запись / запись внутреннего воспроизведения звука приложения Android и экспорт mp3? Подавить Gradle Warning в Android Studio? OnCreate (…) вызывается дважды после поворота устройства Как отключить прокрутку ViewPager с помощью android-support-v4.jar в android