Android-анимация не завершена в OnAnimationEnd - PullRequest
65 голосов
/ 20 января 2011

Кажется, что анимация андроида действительно не завершена, когда происходит событие 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 ]

91 голосов
/ 25 февраля 2011

Вот фактическая ошибка, связанная с этой проблемой 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.

Это работает правильно, и больше нет мерцания в конце анимации. Надеюсь, это поможет.

32 голосов
/ 13 апреля 2011

Я был в состоянии решить эту проблему, вызвав 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);
6 голосов
/ 08 сентября 2013

У меня была похожая проблема, и я использовал решение Сохэма с пользовательским классом представления.

Это работало нормально, но в конце концов я нашел более простое решение, которое работало для меня.

После вызова view.StartAnimation(animation) и перед следующим шагом в моей программе я добавил небольшую задержку, которая будет достаточной для завершения анимации, но достаточно короткой для того, чтобы пользователь ее не заметил

new Handler().postDelayed(new Runnable() {
       @Override
       public void run() {
           nextStepInMyProgram();
       }
     }, 200);// delay in milliseconds (200)
5 голосов
/ 10 сентября 2014

У меня была та же проблема, и я решил ее, используя

view.clearAnimation();

до

view.startAnimation(anim);
2 голосов
/ 09 июня 2016

Попробуйте использовать 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
            }
        });
}
2 голосов
/ 08 февраля 2011

По какой-то причине onAnimationStart работает правильно, а onAnimationEnd - нет. Вот как я это сделал и что изменил:

Попытка 1 (мерцание): а) Переместить изображение с 0 на 80 пикселей б) В onAnimationEnd установите местоположение изображения в 80px

Попытка 2 (без мерцания): а) В onAnimationStart установите местоположение изображения на 80 пикселей б) Переместить изображение с -80px на 0px

Надеюсь, это имело смысл. В основном я перевернул способ, которым я это сделал

1 голос
/ 31 июля 2015

анимация также может быть остановлена ​​при повороте экрана.в этом случае 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);
0 голосов
/ 28 марта 2018

Если вы используете счетчик повторений как бесконечный, то onAnimationEnd не будет вызван.Проверьте документацию ссылка

0 голосов
/ 24 сентября 2015

У меня была эта проблема, потому что мой Animation не был запущен в главном потоке. Это привело к duration 0. Тем не менее, Animation сыграл правильно - он просто вызвал onAnimationEnd() сразу после выполнения.

0 голосов
/ 29 июня 2015

Простое решение - добавить одну строку к AnimationListener.onAnimationEnd():

@Override 
public void onAnimationEnd(Animation a) {
    a.setAnimationListener(null);
    …
}
...