Попытка сбросить значения из Property Animator для использования в представлении ресайклера

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

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

Как я могу сбросить представления в исходное состояние? Я пробовал много подходов из сообщений, но никто не решил это. Самое близкое определение, которое я получил, было в этом посте без ответа: animates-its-some-p">Как сбросить представление в исходное состояние после использования аниматоров для анимации некоторых его свойств?

Вот пример того, как я настроил свою анимацию в onBind (здесь есть попытка использовать onAnimationEnd, которую я нашел в одном посте, но она не сработала)

ObjectAnimator scaleXUp = ObjectAnimator.ofFloat(mView, View.SCALE_X, 10f);
        scaleXUp.setRepeatCount(ValueAnimator.INFINITE);
        scaleXUp.setRepeatMode(ValueAnimator.REVERSE);
        scaleXUp.setDuration(700);
        ObjectAnimator scaleYUp = ObjectAnimator.ofFloat(mView, View.SCALE_Y, 10f);
        scaleYUp.setRepeatCount(ValueAnimator.INFINITE);
        scaleYUp.setRepeatMode(ValueAnimator.REVERSE);
        scaleYUp.setDuration(700);
        mTotalAnimation = new AnimatorSet();
        mTotalAnimation.play(scaleXUp).with(scaleYUp);
        mTotalAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
        mTotalAnimation.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                animation.removeListener(this);
                animation.setDuration(0);
                for(Animator va : ((AnimatorSet)animation).getChildAnimations()) {
                    ((ValueAnimator)va).reverse();
                }
            }
        });
        mTotalAnimation.start();

И вот что я делаю в onUnbindData:

if (mTotalAnimation != null) {
        mTotalAnimation.end();
        mTotalAnimation = null;
    }

И, как я видел, многим нравится подход clearAnimation - пробовали и тоже не сработало.


person Alon    schedule 11.08.2017    source источник


Ответы (1)


4 дня и ни одного ответа, а между тем решил сам. Значит, подход был близким, просто неправильно поставленным.

Я добавил этот метод:

private void stopAnimation() {
    for (Animator anim : mTotalAnimation.getChildAnimations()) {
        ((ObjectAnimator) anim).reverse();
        anim.end();
    }
}

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

Здесь я получаю анимацию из AnimatorSet, переворачиваю и заканчиваю каждую. Я не понял, почему мне пришлось делать это вручную, но похоже, что эта возможность будет добавлена ​​в Android O: https://developer.android.com/preview/api-overview.html#aset

Начиная с Android O, API AnimatorSet теперь поддерживает поиск и воспроизведение в обратном порядке. Поиск позволяет установить положение набора анимации в определенный момент времени. Воспроизведение в обратном порядке полезно, если ваше приложение включает анимацию для действий, которые можно отменить. Вместо определения двух отдельных наборов анимаций вы можете воспроизвести один и тот же в обратном порядке.

person Alon    schedule 15.08.2017
comment
Я не думаю, что end() нужно. Кажется, это отменяет эффект reverse(). Кроме того, для немедленного сброса значений в исходное состояние вам понадобится anim.setDuration(0) перед вызовом anim.reverse(). Также я заметил, что вызов mTotalAnimation.setDuration(0) не имел никакого эффекта, его нужно было вызывать для каждой дочерней анимации. - person owjsub; 10.01.2018