Android ValueAnimator有一个无限调用cancel(),如果它是从startListener调用的
我有两个Android ValueAnimator有一个无限调用cancel(),如果它是从startListener调用的,android,user-interface,animation,listener,Android,User Interface,Animation,Listener,我有两个ValueAnimator实例,它们在onClickListener中启动-一个向上移动视图,另一个向下移动相同的视图。每个动画都有一个startListener,因此当一个动画开始时,第二个动画被称为cancel()。IE如果动画,说起来,在中间中断,则导致动画下降,然后取消()/代码>应该工作,但是如果我在动画上设置 StaskOffice ,注销()/代码> > SististeNave/Cuth>多次工作(如在一个循环中),然后我有一个 StaskOfFultError 我
ValueAnimator
实例,它们在onClickListener
中启动-一个向上移动视图
,另一个向下移动相同的视图。每个动画都有一个startListener
,因此当一个动画开始时,第二个动画被称为cancel()
。IE如果动画,说起来,在中间中断,则导致动画下降,然后<代码>取消()/代码>应该工作,但是如果我在动画上设置<代码> StaskOffice <代码>,<代码>注销()/代码> <代码> > SististeNave/Cuth>多次工作(如在一个循环中),然后我有一个<代码> StaskOfFultError
我注意到相同的错误将在没有startOffset
的情况下出现,但是如果我调用两个动画,则在相同的view
中开始,而在第一个动画中不调用cancel()
。但是cancel()
在startListener
(!)中调用。当动画以anim.start()
本机启动时,startListener
不起作用,仅在startOffset延迟结束后。
代码:
问题:如果我在第一次startOffset
结束之前将动画更改为第二个动画,为什么在循环+StackOverflowerError
中调用onStartListener
上的cancel()
(尽管如果我在启动延迟后调用新动画,一切正常)以及如何修复它?我认为这是因为您正在设置当前播放时间。它作为一个新对象启动动画,而旧对象保留对视图的引用,因此没有去硝化,因此您将获得StackOverflowException
。正在尝试从侦听器中删除settercallback@HawkPriest,我从onStartLisneters
中删除了setCurrentTime
,并在调用anim.start()
之前分配了它,但这并没有解决问题。我可能做错什么事,或者做别的事。我尝试删除onStartListener
中的UpdateListener
(是的,即使如此),然后再次设置,但这并没有解决问题
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();
}
}
}