Подтвердить что ты не робот

OnAnimationEnd не получает вызов, onAnimationStart работает нормально

У меня есть ScrollView в PopupWindow. Я анимация содержимого ScrollView с помощью TranslateAnimation.

Когда начинается анимация, вызывается прослушиватель onAnimationStart, но onAnimationEnd не вызывается. Любые идеи?

Макет:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   android:background="@drawable/popup_window_bg"
   android:layout_width="match_parent"
   android:layout_height="wrap_content">
  <View
     android:layout_width="@dimen/toolbar_padding_left"
     android:layout_height="@dimen/toolbar_height"/>
  <ScrollView
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+web/toolbar"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:scrollbars="none"
     android:visibility="invisible">
    <LinearLayout
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:orientation="vertical">

       ...

    </LinearLayout>
  </ScrollView>
</LinearLayout>

Анимационный код:

mToolbar = mPopupContents.findViewById( R.web.toolbar );
TranslateAnimation anim =
    new TranslateAnimation(0, 0, -60, 0);
anim.setDuration(1000);
anim.setAnimationListener(new Animation.AnimationListener() {
        public void onAnimationStart(Animation a) {
            Log.d(LOGTAG, "---- animation start listener called"  );
        }
        public void onAnimationRepeat(Animation a) {}
        public void onAnimationEnd(Animation a) {
            Log.d(LOGTAG, "---- animation end listener called"  );
        }
    });
mToolbar.startAnimation(anim);

Обновить. Я проверял, что onAnimationEnd вызывается, но вызывается после некоторой задержки (если вы не запустили новую анимацию за это время).

4b9b3361

Ответ 1

AnimationEnd не является надежным. Если вы не хотите переписывать свой код с пользовательскими представлениями, которые переопределяют OnAnimationEnd, используйте postDelayed.

Вот пример кода:

final FadeUpAnimation anim = new FadeUpAnimation(v);
anim.setInterpolator(new AccelerateInterpolator());
anim.setDuration(1000);
anim.setFillAfter(true);
new Handler().postDelayed(new Runnable() {
    public void run() {
        v.clearAnimation();
        //Extra work goes here
    }
}, anim.getDuration());
v.startAnimation(anim);

Пока он МОЖЕТ казаться уродливым, я могу гарантировать его надежность. Я использую его для ListViews, которые вставляют новые строки при удалении с анимацией в другие строки. Стресс-тестирование слушателя с AnimationEnd оказалось ненадежным. Иногда AnimationEnd никогда не запускался. Возможно, вы захотите повторно применить любое преобразование в функции postDelayed, если анимация не будет полностью закончена, но это действительно зависит от того, какой тип анимации вы используете.

Ответ 2

После того, как я не помню, как сообщения чтения и дни, потраченные на обнаружение решения этой проблемы, я обнаружил, что если объект для перемещения не находится в области экрана (например, помещен из экранных коордов) OnAnimationEnd callback не вызывается. Вероятно, анимация завершилась неудачей сразу после запуска (вызывается метод start, я кодировал прослушиватель), но ничего не записывается в logcat. Возможно, это не совсем ваше дело, но это, наконец, решило мою проблему и надеюсь, что это тоже поможет вам.

Ответ 3

убедитесь, что используется view.startAnimation(Animation) И НЕ view.setAnimation(Animation). Эта простая путаница может быть проблемой.

-Cheers

Ответ 4

Кроме того, при использовании анимации не забывайте setFillAfter() - true.

http://developer.android.com/reference/android/view/animation/Animation.html#setFillAfter(boolean)

Если fillAfter истинно, преобразование, которое выполняет эта анимация, сохранится, когда оно будет завершено. По умолчанию установлено значение false, если оно не установлено. Обратите внимание, что это применимо при использовании AnimationSet для анимации цепочек. Преобразование не применяется до запуска самого AnimationSet.

anim.setFillAfter(true);
mToolbar.startAnimation(anim);

Ответ 5

Для тех, кто наткнулся на этот вопрос: перейдем к использованию системы Property Animation вместо http://developer.android.com/guide/topics/graphics/prop-animation.html

У меня было несколько проблем со старым способом анимации fade-in/out в представлении (через AlphaAnimation). OnAnimationEnd не вызывается и т.д. С помощью анимации свойств все эти проблемы были устранены.

Если вы хотите поддерживать устройства API < 11, Jake Wharton https://github.com/JakeWharton/NineOldAndroids - это путь

Ответ 6

Вы не устанавливаете другую анимацию до того, что вы ожидаете, заканчивается?

Без контекста трудно понять, если это что-то вроде этого... но это, вероятно, одна из единственных вещей, которые могли бы вызвать его.

Ответ 7

Я предполагаю, что его вызывается через некоторое время, потому что вы используете setDuration для анимации и пропустите 1000 мс в нем. Просто пройдите 0, и вам не потребуется время, чтобы позвонить.

Ответ 8

Задержка, вероятно, связана с anim.setDuration(1000), или если вы делаете это в потоке, то, вероятно, из-за переключения контекста. Попробуйте манипулировать временем задержки и посмотрите, заметили ли вы какую-либо разницу.

Ответ 9

Попробуйте использовать overridePendingAnimation (int, int). то есть overridePendingAnimation (0,0)

Он переопределит вашу анимацию по умолчанию, а затем вы сможете определить собственную анимацию. Вызовите метод startAnimation с помощью объекта View.

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

overridePendingTransition(0,0);
//finish();
v.startAnimation(AnimationUtils.loadAnimation(getApplicationContext(), R.anim.fadeout));
startActivity(new Intent(ContentManagerActivity.this,Mainmenu_activity.class));
overridePendingTransition(R.anim.fadein,0);

Ответ 10

Я пробовал ваш код, он отлично работает при запуске OnAnimation и inAmimationEnd, также после того, как время продолжительности означает, что после финализации анимации onAnimationEnd вызывается, поэтому ваш код работает нормально

TranslateAnimation anim =new TranslateAnimation(0, 0, -60, 0);
        anim.setDuration(1000);     
        anim.setAnimationListener(new Animation.AnimationListener() {
                public void onAnimationStart(Animation a) {
                    Log.w("Start", "---- animation start listener called"  );
                }
                public void onAnimationRepeat(Animation a) {}
                public void onAnimationEnd(Animation a) {
                    Log.d(" end  ","---- animation end listener called"  );
                }
            });
            mIv.setAnimation(anim);
            mIv.startAnimation(anim);

Ответ 11

Возможно, у кого-то все еще есть эта проблема и не найдено решение - даже если вы читаете много ответов на stackoverflow - как и я!

Итак, мой случай: я использовал animatorSet и

  • не было ни одного представления, которое я мог бы назвать clearAnimation on,
  • Я не вызывал свою анимацию из backgroundThread, которой вы никогда не должны этого делать, btw-

В качестве решения я действительно звонил animatorSet.end() прямо перед animatorSet.start()

Ответ 12

Когда вы запускаете команду анимации в частично отдаленном представлении, запускается запуск анимации и onStartListener, но анимация не запускается полностью (так или иначе она прерывается посередине). Я предполагаю, что, поскольку представление вне экрана, оно отменяется, и поэтому он не вызывается. В качестве обходного пути для этого я создал свой собственный прослушиватель анимации, который запускает обработчик и использует postDelayed для уведомления пользователя о событии конца анимации. В Котлине:

abstract class PartiallyOffScreenAnimationListener : Animation.AnimationListener, AnimationListener {
    override fun onAnimationRepeat(animation: Animation?) {
        onAnimationRepeat_(animation)
    }
    override fun onAnimationEnd(animation: Animation) {}

    override fun onAnimationStart(animation: Animation) {
        onAnimationStart_(animation)
        Handler().postDelayed({
            onAnimationEnd_(animation)
            animation.setAnimationListener(null)
        }, animation.duration + 50)
    }
}

Обратите внимание, что в случае, если анимация не выполняется полностью, представление может быть оставлено в несогласованном состоянии (например, анимирование параметров макета может привести к удалению странного среднего фактора интерполяции. По этой причине вы должен проверить в конце обратного вызова, что представление находится в желаемом состоянии. Если нет, просто установите его вручную.

Ответ 13

Сделайте это, как belows

  • сделать анимацию окончательной
  • вызывать его внутри обработчика
  • прослушиватель должен быть создан один раз.
  • очистить анимацию.

например view.clearAnimation();

new Hander().post(
   run() {
final TranslateAnimation ani = new TranslateAnimation(0, 0, 0, 0);
ani.setAnimationListener(mListener);
 }
);

private Animation.AnimationListener mListener = new Animation.AnimationListener() {
}

Ответ 14

С чего начать анимацию? Если в onCreate это неправильно. Попробуйте сделать это в onResume.