Я пытаюсь сделать простую анимацию, которая повторялась бы несколько раз (или бесконечно).
Вроде 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
и с рядом других атрибутов.Я потратил несколько часов на то, чтобы выяснить, с чем он может и чего не может справиться, и отправил отчет об ошибке / проблему здесь: Проблема 17662
В итоге (это касается
AnimationSet
s):источник
Я обнаружил, что тег <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); }
источник
Я также столкнулся с той же проблемой ... я включил 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);
Это будет повторять анимацию бесконечно.
источник
repeatMode
должно быть либо,RESTART
либоREVERSE
Я попытался использовать код Дэниела, чтобы показывать анимацию точное количество раз, и у меня возникла проблема: анимация показывалась примерно 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); } } } } //...
При использовании варианта, показанного выше, анимация показывается точно REPEAT_COUNT раз, поскольку метод View.post () дает возможность начать новую анимацию после завершения всех действий, связанных с предыдущей анимацией.
источник
вам нужно добавить только одну строку в свой 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>
источник
Я решил эту проблему, используя
android:repeatMode="reverse"
ранее в своем проекте.<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" />
источник
С 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 означает количество повторений.
источник
Я делаю большую часть своих вещей программно, и я могу опоздать или неэффективно в этом, но это, но я выполнил цель набора повторяющейся анимации (у меня даже есть 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();
источник
Я столкнулся с той же проблемой, но не хотел делать какие-либо временные действия в 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:
источник
Нужно прослушать завершение первой анимации, а затем повторно запустить анимацию в обратном вызове 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);
источник
Я решил эту проблему с помощью потока.
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 раза. Вы можете добавить больше копий, чтобы повторить это определенное время, добавив значения смещения.
источник
Попробуйте добавить код в поток цикла или оператор while / for
источник