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);
Делает один цикл, а затем заканчивается.
Он масштабируется, затем масштабируется и затем останавливается.
Как я могу сделать эту работу по назначению?
Ответы
Ответ 1
Обновление:. В сентябре 2011 года разработчик Android исправил эту проблему по большей части. Атрибуты, которые были проигнорированы в XML, теперь работают, за исключением repeatCount
и fillEnabled
, которые по-прежнему игнорируются (по какой-то причине). Это означает, что пока нелегко повторить AnimationSet
.
Подробнее см. обзор в обновленных документах (объясняет, какие атрибуты игнорируются, какие работают и которые передаются детям). И для более глубокого понимания того, что fillAfter
, fillBefore
и fillEnabled
на самом деле, см. Сообщение администратора (Chet Haase) об этом здесь.
Оригинальный ответ
Чтобы расширить ответы Павла и других: это правда, что тег <set>
смехотворно глючит. Он не может корректно работать с repeatCount
и рядом других атрибутов.
Я потратил несколько часов на то, чтобы выяснить, что он может и не может решить, и представил здесь отчет об ошибке: Проблема 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.
Ответ 2
Я обнаружил, что тег <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"
/>
К сожалению, это ограничивается только одной анимацией сразу.
Мы не можем определить последовательность анимаций таким образом...
Ответ 3
Вы должны включить атрибут
android:repeatCount="infinite"
Но в вашей "масштабной" анимации не в "set"
Ответ 4
Чтобы получить повторяющуюся анимацию, я использовал прослушиватель анимации и снова вызвал анимацию, когда она закончилась. Это делает ретикулу камеры, фокусируясь как анимация с помощью скобок.
Вот макет анимации 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);
}
Ответ 5
вы можете попробовать этот код.
В свой код просто добавьте
firstAnimation.setRepeatCount(5);
Это повторит анимацию в течение определенного времени
firstAnimation.setRepeatCount(Animation.INFINITE);
firstAnimation.setRepeatMode(Animation.INFINITE);
Это повторит анимацию неограниченно.
Ответ 6
У меня тоже была проблема.
Я включил 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"/>
Ответ 7
Я попытался использовать код Дэниэля, чтобы показать анимацию точное количество раз, и возникла проблема: анимация была показана аппроксимативно n/2 раза, когда n ожидалось.
Итак, я изменил код Daniel:
//...
@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() дает возможность запускать новую анимацию после завершения всех действий, связанных с предыдущей анимацией.
Ответ 8
С android sdk версия 4.0.3:
В данных анимационных элементах:
Android: RepeatCount = "- 1"
делает его бесконечной анимацией.
Ответ 9
Добавьте в свой проект следующий класс:
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 обозначает количество повторений.
Ответ 10
Я делаю большую часть своих программных продуктов, и я могу опаздывать или неэффективно в этом, но это, но я выполнил цель повторного анимации (у меня даже есть 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
}
});
}
Очистка и аннулирование, когда только предыдущие попытки и правильное использование этой вещи. Я не знаю, нужны они или нет.
Надеюсь, это поможет кому-то.
Райан
Ответ 11
У меня это получилось... я пытался получить представление для вращения по кругу непрерывно.
предыдущий я использовал rotation.setRepeatMode(-1), но это не сработало. переключился на setrepeatcount, и он работает. Это на желе bean 4.2.2
ObjectAnimator rotation = ObjectAnimator.ofFloat(myview,
"rotation", 360).setDuration(2000);
rotation.setRepeatMode(-1);
rotation.setRepeatCount(Animation.INFINITE);
rotation.start();
Ответ 12
Попробуйте добавить код в поток цикла или оператор while/for
Ответ 13
Я столкнулся с той же проблемой, но не хотел делать какие-либо события синхронизации на 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 из моего макета.
Ответ 14
Я решил эту проблему. Это моя версия исправления:
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) {
}
}
}
Ответ 15
Я просто столкнулся с этой проблемой, работая над обратным совместимым приложением. так расстраивает! я закончил кодирование хорошего класса обходного пути, который можно вызывать из onCreate и будет запускать любой ресурс анимации в неопределенный цикл.
класс, AnimationLooper, доступен здесь:
https://gist.github.com/2018678
Ответ 16
После изучения ответов из Интернета я нашел решения, которые отлично подходят для меня. (И да, 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
Ответ 17
Нужно прослушать завершение первой анимации, а затем повторно запустить анимацию в обратном вызове onStopAnimation, попробовать эту ссылку p >
Ответ 18
Маленькая настройка для ответа @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);
Ответ 19
Я решил эту проблему, используя обратное в моем проекте.
<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"
/>
Ответ 20
Я решил эту проблему, используя 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
}
});
Ответ 21
работает нормально
GifDrawable gifDrawable = (GifDrawable) gifImageView.getDrawable();
gifDrawable.setLoopCount(0);
Ответ 22
Ни один из вышеперечисленных решений не работал в моем случае. Решение 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 раза. Вы можете добавить больше копий, чтобы повторить определенное время, добавив значения смещения.