Андроидная анимация не завершена inAnimationEnd

Кажется, что анимация андроида действительно не закончена, когда событие onAnimationEnd запущено, хотя для параметра animation.hasEnded установлено значение true.

Я хочу, чтобы мое представление меняло его фоном на конец его ScaleAnimation, который он делает, но вы можете ясно видеть, что он изменил некоторые миллисекунды, прежде чем он закончит. Проблема в том, что он мерцает, потому что новый фон появляется (= is) масштабируется в течение короткого времени, пока анимация не закончится.

Есть ли способ получить либо реальный конец анимации, либо просто предотвратить новый масштаб от этого короткого периода времени?

Спасибо!


//EDIT: я использую 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
}

Ответ 1

Вот фактическая ошибка, связанная с этой проблемой http://code.google.com/p/android-misc-widgets/issues/detail?id=8

В основном это означает, что метод onAnimationEnd не работает хорошо, когда AnimationListener подключен к анимации

Обходной путь заключается в прослушивании событий анимации в представлении, к которому вы применяли анимацию, чтобы Например, если изначально вы добавляли прослушиватель анимации к анимации, подобной этой

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
}

Это правильное решение этой проблемы, обеспечивающее функциональность в методе over-riden View → onAnimationEnd, в отличие от метода onAnimationEnd AnimationListener, связанного с анимацией.

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

Ответ 2

Я решил устранить это, вызвав clearAnimation() в анимированном представлении внутри onAnimationEnd, что убрало мерцание Странно, почему кто-то должен это делать, так как onAnimationEnd callback должен был быть вызван только в том случае, если анимация уже закончилась. Но я думаю, что ответ кроется в глубине 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);

Ответ 3

У меня была аналогичная проблема, и я использовал решение Soham с пользовательским классом вида.

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

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

new Handler().postDelayed(new Runnable() {
       @Override
       public void run() {
           nextStepInMyProgram();
       }
     }, 200);// delay in milliseconds (200)

Ответ 4

У меня была такая же проблема и она была решена с помощью

view.clearAnimation();

перед

view.startAnimation(anim);

Ответ 5

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

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

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

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

Ответ 6

Попробуйте использовать 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
            }
        });
}

Ответ 7

Легкое исправление заключается в добавлении одной строки в AnimationListener.onAnimationEnd():

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

Ответ 8

annimation также может быть остановлена ​​при вращении экрана. в этом случае 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);

Ответ 9

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

Ответ 10

Это сработало для меня:

@Override
public void onAnimationUpdate(ValueAnimator animation) {
    if (Float.compare(animation.getAnimatedFraction(),1.0f)) {
    // animation ended;
        //do stuff post animation
    }
}