У меня есть два экземпляра ValueAnimator
, которые запускаются внутри onClickListener
- один перемещает view
вверх, другой перемещает тот же view
вниз. Каждая анимация имеет startListener
, поэтому при запуске вторая называется cancel()
. Т.е. если анимация, скажем, вверх, прерывается в середине, - заставить анимацию идти вниз, тогда cancel()
должно работать, и это работает, но если я установлю startOffset
для обеих анимаций, cancel()
в startListener
работает много раз (как в цикле), а затем у меня есть stackOverFlowError
.
Я заметил, что та же ошибка будет и без startOffset
, но если я вызову, обе анимации начинаются с одного и того же view
без вызова cancel()
при первой анимации. Но cancel()
вызывается изнутри startListener
(!). И startListener
не работает, когда анимация начинается с anim.start()
, только после окончания задержки startOffset.
Код:
Float firstLevelUp = 200f;
Float firstLevelDown = 0f;
long duration = 1500l;
ValueAnimator valueAnimatorView1Down = ValueAnimator.ofFloat(firstLevelUp,firstLevelDown);
ValueAnimator valueAnimatorView1Up = ValueAnimator.ofFloat(firstLevelUp,firstLevelDown);
public void initAnim(final View view){
valueAnimatorView1Down.setDuration(duration);
valueAnimatorView1Up.setDuration(duration);
valueAnimatorView1Down.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
if (valueAnimatorView1Up.isStarted()) {
valueAnimatorView1Up.cancel();
valueAnimatorView1Down.setCurrentPlayTime(duration - valueAnimatorView1Up.getCurrentPlayTime());
Log.i("Down View1 animation " , "STARTED WITH CANCEL");
}else {
Log.i("Down View1 animation " , "STARTED WITHOUT CANCEL");
}
}
@Override
public void onAnimationCancel(Animator animation) {
Log.i("DownView1 animation " , "CANCELED");
}
});
valueAnimatorView1Up.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
if (valueAnimatorView1Down.isStarted()) {
valueAnimatorView1Down.cancel();
valueAnimatorView1Up.setCurrentPlayTime(duration - valueAnimatorView1Down.getCurrentPlayTime());
Log.i("Up View1 animation " , "STARTED WITH CANCEL");
}else {
Log.i("Up View1 animation " , "STARTED WITHOUT CANCEL");
}
}
@Override
public void onAnimationCancel(Animator animation) {
Log.i("Up View1 animation " , "CANCELED");
}
});
valueAnimatorView1Down.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
view.setTranslationY((Float) valueAnimatorView1Down.getAnimatedValue());
}
});
valueAnimatorView1Up.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
view.setTranslationY((Float) valueAnimatorView1Up.getAnimatedValue());
}
});
}
public void startViewAnimation(boolean side) {
if (side) {
Log.i("Down animations ", "start()");
valueAnimatorView1Down.setStartDelay(800);
valueAnimatorView1Down.start();
} else {
Log.i("Up animations ", "start()");
valueAnimatorView1Up.setStartDelay(800);
valueAnimatorView1Up.start();
}
}
}
Вопросы: почему cancel()
на onStartListener
вызывается в цикле + stackOverFlowError
, если я изменяю анимацию на вторую, прежде чем startOffset
закончится в первой (хотя, если я вызываю новая анимация после задержки запуска - все работает правильно) и как это исправить?