Android-анимация не завершена в OnAnimationEnd
Кажется, что Android-анимация не закончена, когда onAnimationEnd
событие происходит хотя animation.hasEnded
установлен в true.
Я хочу, чтобы мой взгляд изменил его фон в конце ScaleAnimation
что он делает, но вы можете ясно видеть, что он изменяется за несколько миллисекунд до его завершения. Проблема в том, что он мерцает, потому что новый фон появляется (=is) в течение короткого времени, пока анимация действительно не закончится.
Есть ли способ получить реальный конец анимации или просто предотвратить масштабирование нового фона в этот короткий промежуток времени?
Спасибо!
// РЕДАКТИРОВАТЬ: я использую AnimationListener
чтобы получить следующий звонок:
@Override
public void onAnimationEnd(Animation animation)
{
View view = (MyView) ((ExtendedScaleAnimation) animation).getView();
view.clearAnimation();
view.requestLayout();
view.refreshBackground(); // <-- this is where the background gets changed
}
11 ответов
Вот реальная ошибка, связанная с этой проблемой. http://code.google.com/p/android-misc-widgets/issues/detail?id=8
В основном это говорит о том, что метод onAnimationEnd не очень хорошо работает, когда AnimationListener присоединен к Animation
Обходной путь - прослушивать события анимации в представлении, к которому вы применяли анимацию. Например, если изначально вы подключали слушателя анимации к анимации, как это
mAnimation.setAnimationListener(new AnimationListener() {
@Override
public void onAnimationEnd(Animation arg0) {
//Functionality here
}
});
а затем применить к анимации в ImageView, как это
mImageView.startAnimation(mAnimation);
Чтобы обойти эту проблему, вы должны теперь создать собственный ImageView
public class MyImageView extends ImageView {
а затем переопределить onAnimationEnd
метод класса View и обеспечить все функции там
@Override
protected void onAnimationEnd() {
super.onAnimationEnd();
//Functionality here
}
Это правильный обходной путь для этой проблемы, предоставьте функциональность в переопределенном методе View -> onAnimationEnd в противоположность методу onAnimationEnd объекта AnimationListener, присоединенного к Animation.
Это работает правильно, и больше нет мерцания в конце анимации. Надеюсь это поможет.
Я был в состоянии решить эту проблему, вызвав clearAnimation() для представления, анимированного внутри onAnimationEnd, который убрал мерцание. Это странно, почему кто-то должен был это делать, поскольку обратный вызов onAnimationEnd должен был вызываться, только если анимация уже закончилась. Но я думаю, что ответ лежит в глубине Framework о том, как view / layout обрабатывает обратный вызов анимации. А пока примите это как решение без взлома, которое просто работает.
animation.setAnimationListener(new AnimationListener() {
public void onAnimationEnd(Animation anim) {
innerView.clearAnimation(); // to get rid of flicker at end of animation
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams
(innerBlockContainer.getWidth(), innerBlockContainer.getHeight());
/* Update lp margin, left/top to update layout after end of Translation */
ViewGroup parent_ofInnerView = (ViewGroup)innerView.getParent();
vp.updateViewLayout(innerBlockContainer, lp);
}
public void onAnimationRepeat(Animation arg0) {}
public void onAnimationStart(Animation arg0) {
}
});
innerView.startAnimation(animation);
У меня была та же проблема, и я решил ее, используя
view.clearAnimation();
до
view.startAnimation(anim);
У меня была похожая проблема, и я использовал решение Сохема с классом пользовательского представления.
Это работало нормально, но в конце концов я нашел более простое решение, которое сработало для меня.
После вызова view.StartAnimation(animation)
и перед следующим шагом в моей программе я добавил небольшую задержку, которая будет достаточно длинной, чтобы анимация заканчивалась, но достаточно короткой, чтобы быть незаметной для пользователя:
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
nextStepInMyProgram();
}
}, 200);// delay in milliseconds (200)
По какой-то причине onAnimationStart работает правильно, а onAnimationEnd - нет. Вот как я это сделал и что изменил:
Попытка 1 (мерцание): a) Переместите изображение с 0px на 80px. B) В onAnimationEnd установите местоположение изображения на 80px.
Попытка 2 (без мерцания): a) В onAnimationStart установите местоположение изображения равным 80px. B) Переместите изображение с -80px на 0px.
Надеюсь, что это имело смысл. В основном я перевернул способ, которым я это сделал
Попробуйте использовать getAnimation() из вашего объекта:
public void onShowListBtnClick(View view)
{
rightPanel.startAnimation(AnimationUtils.loadAnimation(MainActivity.this, R.anim.slide_left));
rightPanel.getAnimation().setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
// TODO Auto-generated method stub
}
@Override
public void onAnimationRepeat(Animation animation) {
// TODO Auto-generated method stub
}
@Override
public void onAnimationEnd(Animation animation) {
// write your code here
}
});
}
Анимация также может быть остановлена при повороте экрана. в этом случае onAnimationEnd() не вызывается. мой обходной путь:
animation.setDuration(animationDuration);
animation.setAnimationListener(new AnimationListenerAdapter() {...});
view.startAnimation(animation);
handler.postDelayed(new Runnable() {
@Override
public void run() {
if(!animation.hasEnded()) {
// here you can handle this case
}
}
}, animationDuration + 100);
Простое решение - добавить одну строку в AnimationListener.onAnimationEnd()
:
@Override
public void onAnimationEnd(Animation a) {
a.setAnimationListener(null);
…
}
Если вы используете счетчик повторений как бесконечный, то onAnimationEnd не будет вызван. Проверьте ссылку на документацию
У меня была эта проблема, потому что мой Animation
не был запущен в основной теме. Это привело к duration
0. Однако Animation
действительно играл правильно - он просто позвонил onAnimationEnd()
сразу после исполнения.
Вы также можете использовать
setUpdateListener
, затем проверьте текущую часть прогресса анимации и действуйте соответствующим образом.
Вот пример Kotlin для затухающей анимации, которая в конечном итоге заставляет представление исчезнуть из макета:
view.animate()
.alpha(0f)
.setDuration(duration)
.setUpdateListener { animation ->
if (animation.animatedFraction > 0.99f) {
view.visibility = View.GONE
}
}
.start()
Это сработало для меня:
@Override
public void onAnimationUpdate(ValueAnimator animation) {
if (Float.compare(animation.getAnimatedFraction(),1.0f)) {
// animation ended;
//do stuff post animation
}
}