Android анимация не повторяется
Я пытаюсь сделать простую анимацию, которая будет повторяться несколько раз (или бесконечно).
Кажется, что 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);
Он делает один цикл и после этого заканчивает.
Он масштабируется вверх, затем масштабируется вниз и затем останавливает.
как я могу сделать эту работу так, как задумывалось?
23 ответа:
обновление: еще в сентябре 2011 года инженер Android исправил эту проблему по большей части. Атрибуты, которые были проигнорированы в XML теперь работают, за исключением
repeatCount
иfillEnabled
которые по-прежнему игнорируются (специально по какой-то причине). Это означает, что все еще нелегко повторитьAnimationSet
к сожалению.для получения дополнительной информации см. Обзор в обновленная документация (объясняет, какие атрибуты игнорируются, какие работают, а какие передаются дети.) И для более глубокого понимания чего
fillAfter
,fillBefore
иfillEnabled
на самом деле, смотрите сообщение в блоге инженера (Chet Haase) об этом здесь.
Оригинальный Ответ
чтобы расширить ответы Павла и других: это правда, что
<set>
тег смешно глючит. Он не может правильно справиться сrepeatCount
и ряд других атрибутов.я провел несколько часов, выясняя, что он может и не может иметь дело и иметь отправлено сообщение об ошибке / проблема здесь:вопрос 17662
вкратце (это касается
AnimationSet
s):setRepeatCount () / android: repeatCount
этот атрибут (а также repeatMode) не работает в коде или XML. Это затрудняет повторение всего набора анимаций.
setDuration () / android: длительность
установка этого на AnimationSet в код работает (переопределяет все длительности дочерних анимаций), но не при включении в тег в XML
setFillAfter () / android: fillAfter
это работает как в коде, так и в XML для тега. Как ни странно, я получил его, чтобы также работать без необходимости устанавливать fillEnabled в true.
setFillBefore () / android:fillBefore
кажется, не имеет никакого эффекта / игнорируется в коде и XML
setFillEnabled () / android: fillEnabled
кажется, не имеет никакого эффекта / игнорируется как в коде, так и в XML. Я все еще могу заставить fillAfter работать даже без включения fillEnabled или установки fillEnabled в false.
setStartOffset () / android: startOffset
это работает только в коде, а не XML.
Я нашел это тег имеет багги реализации в классе AnimationSet.
Он не может правильно справиться с repeatCount.
Что мы можем сделать, - это установить repeatCount непосредственно в - тег.
Этот 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" />
к сожалению, это ограничено только одной анимацией сразу.
Мы не можем определить последовательность анимации это путь...
чтобы получить повторяющуюся анимацию, я использовал прослушиватель анимации и снова вызвал анимацию, когда она закончилась. Это делает сетку камеры фокусировки, как анимация с скобками.
вот макет анимации 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); }
Я также столкнулся с той же проблемой.. я включил android: repeatCount= "infinite" в 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"/>
вы можете попробовать этот код. В вашем коде просто добавьте,
firstAnimation.setRepeatCount(5);
это повторить анимацию в течение определенного времени
firstAnimation.setRepeatCount(Animation.INFINITE); firstAnimation.setRepeatMode(Animation.INFINITE);
это будет повторять анимацию бесконечно.
Я попытался использовать код Даниэля, чтобы показать анимацию точное количество раз и имел проблему: анимация была показана примерно 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 раз, потому что вид.метод post () дает возможность начать новую анимацию после завершения всех действий, связанных с предыдущей анимацией.
с android sdk версии 4.0.3:
в данных элементах анимации:
android: 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 обозначает количество повторений.
Я делаю большую часть своих вещей программно, и я могу опоздать или неэффективно на этом, но это, но я завершил повторение цели animationset (у меня даже есть 2 чередующихся набора анимации). Все,что делает этот код, просто исчезает в одном изображении, пауза, затем исчезает, исчезает в другом изображении, пауза, исчезает и возвращает первый (промыть и повторить). Сначала я определил свои 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);
затем я сделал два таймера, таймеры задач и обработчики, чтобы иметь дело с тем, когда начать и остановить каждая анимация:
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 } }); }
clearanimation и аннулировать, где только предыдущие попытки и получить эту вещь, чтобы работать правильно. Я не знаю, нужны они или нет.
надеюсь, это кому-то поможет.
Райна
Я получил это, чтобы пойти ...я пытался получить вид, чтобы вращаться по кругу непрерывно .
предыдущий я использовал вращение.setRepeatMode(-1), но это не сработало. перешли на setrepeatcount и он работает. Это на jelly bean 4.2.2
ObjectAnimator rotation = ObjectAnimator.ofFloat(myview, "rotation", 360).setDuration(2000); rotation.setRepeatMode(-1); rotation.setRepeatCount(Animation.INFINITE); rotation.start();
вы должны добавить одну строку в XML-код, который я предложил ниже .
<scale 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:repeatCount="infinite" // just add this one line android:fillAfter="false" /> </set>
я столкнулся с той же проблемой, но не хотел делать какие-либо временные вещи в Java из-за того, что поток пользовательского интерфейса может быть очень занят иногда. Бесконечный флаг не работает для тега set. Поэтому я решил проблему с небольшим куском кода:
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-это изображение из моего макета.
Я решил эту проблему. Это моя версия исправления:
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, который очень гибкий. Я бы не рекомендовал использовать анимацию или 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" />
Я решил эту проблему с помощью резьбы.
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 раза. Вы можете добавить больше копий, чтобы повторить его определенное время, добавив значения смещения.