Как уменьшить задержку requestLayout () в анимации? - PullRequest
0 голосов
/ 05 октября 2018

Я пытаюсь анимировать ширину TextView, на моем Redmi Note 4 это работало безупречно.Однако при тестировании на немного более медленном телефоне (четырехъядерный процессор с частотой 1,2 ГГц) анимация была ужасно запаздывающей.

После некоторой начальной отладки выяснилось, что вызов requestLayout() был причиной, он отбросил много кадров, и при дальнейшеминспекция, получившая onMeasure(), , которая является первым методом, вызываемым при перерисовке , называется A LOT только для анимируемой только 1 TextView.Вполне вероятно, что остальная часть родительской иерархии называет его bubblin 'для корня.

Это абсолютно не буэно в моем случае.Я пытаюсь оживить ширину и высоту.Я использую ValueAnimator и звоню requestLayout внутри onAnimationUpdate(), я пытался звонить requestLayout() только внутри одного из них, но это почти не оказывало никакого влияния.

final ViewGroup.LayoutParams layoutParams = container.getLayoutParams();

ValueAnimator anim = ValueAnimator.ofInt(this.width, ((int) (this.screenWidth / 1.5)));
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator valueAnimator) {
        layoutParams.width = (int) (Integer) valueAnimator.getAnimatedValue();
    }
});
anim.setDuration(duration);
anim.start();

anim = ValueAnimator.ofInt(this.height, this.screenHeight / 2);
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator valueAnimator) {
        layoutParams.height = (int) (Integer) valueAnimator.getAnimatedValue();
        container.requestLayout();
    }
});
anim.setDuration(duration);
anim.start();

Я пытался создать кастомStaticLayout, чтобы использовать некоторые из оптимизаций эффективности и производительности этого подхода, но это также не помогло.В конце концов, сам класс View - это то, что постоянно вызывает onMeasure(), так как я могу предотвратить это и только обновить TextView, который я хочу изменить?Конечно, invalidate() не сработает, потому что пропустит работу по изменению размера.

Ответы [ 2 ]

0 голосов
/ 11 октября 2018

После некоторого копания я обнаружил, что использование beginDelayedTransition() с ConstraintSet на ConstraintLayout оказывается более эффективным и плавным, чем ручная анимация.

0 голосов
/ 10 октября 2018

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

одна из причин может быть: - Вы анимируете от определенной ширины до screenWidth / 1.5, который, я думаю, намного больше.

Допустим, вы анимируете от 48 до 480

initialValue: 48

finalValue: 480

длительность: 200ms

Это означает (480-48)= 432 шага / повторное рисование за 200 мс, затем примерно 2 рисования за миллисекунду.

Таким образом, вы даете менее миллисекунды за 1 рисование.В идеале, если время прорисовки превышает 16 мс, то возникают потери кадров.В вашем случае вы пытаетесь слишком много перерисовать из-за вызова requestLayout.

Идеальным условием для рисования 432 кадров является:

1 frame -> 20 ms (some extra time given) 432 frames -> 8640 ms

Попробуйтеуменьшите количество вызовов на requestLayout для предотвращения onMeasure() вызовов.

...