Круговая анимация Reveal onTouch Android - PullRequest
5 голосов
/ 17 марта 2020

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

Во-первых, мой взгляд внутри бесконечной круговой развертки показывает oop, чтобы сохранить округленный аспект, пока пользователь ничего не делает. Затем, когда пользователь коснулся вида и начал сильно ударить, я вычислил коэффициент внутри ACTION_MOVE, чтобы увеличить радиус в реальном времени и вызвать круговое раскрытие при каждом проходе.

public void reveal(final View view,
                               final float centerX,
                               final float centerY,
                               final float startRadius,
                               final float endRadius,
                               final int duration) {

                anim = ViewAnimationUtils.createCircularReveal(view, (int)centerX, (int)centerY, (int)startRadius, (int)endRadius);
                anim.setDuration(duration);
                anim.addListener(new Animator.AnimatorListener() {
                    @Override
                    public void onAnimationStart(Animator animation) {
                    }
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        if (isRepeating) {
                            reveal(view,centerX,centerY,startRadius,endRadius,duration);
                        }
                    }
                    @Override
                    public void onAnimationCancel(Animator animation) {
                    }
                    @Override
                    public void onAnimationRepeat(Animator animation) {
                    }
                });
                anim.start();

    }

Я снова вспомнил метод кругового раскрытия внутри слушателя, чтобы создать l oop и самое важное - избежать визуальных искажений.

Я заметил, что, если бы я не сделал этого, появилось какое-то очень быстрое искажение, потому что продолжительность анимации быстрее, чем каждый проход в ACTION_MOVE, поэтому аним успевает закончить sh до следующего проходить. Искажение - это представление отсутствующей части вида, когда анимация завершена и очень быстро вернулась к текущему радиусу, установленному с помощью Touch как fla sh.

Таким образом, при вызове метода внутри Слушателя все работает прекрасно, пока не будет.

Проблема: На одном из моих устройств при перелистывании возникают бессмысленные искажения во всех направлениях.

enter image description here

Согласно моим журналам, это не искажение радиуса, потому что радиус начала и конца всегда одинаков после каждого прохода, поэтому радиус не должен двигаться так, особенно когда палец остановлен, и анимация никогда не останавливается, спасибо Слушателю, как я объяснил выше.

Что я делаю не так?

Я много искал и не нашел ту же проблему, поэтому я попробовал другие способы, такие как рисование холста, но, к сожалению, это не соответствует моим потребностям.

Есть ли другой способ добиться этого вид анимации, даже совсем по-другому?

Любое руководство приветствуется заранее

РЕДАКТИРОВАТЬ: внутри ACTION_MOVE

 scaleRadius = (float) (2 * distance / maxWidth + startScale);

 if (scaleRadius < 1) {
       scaleRadius = 1;
 }

 animator.reveal(this, middleCircleX, middleCircleY, 
initialCircleRadius*scaleRadius, initialCircleRadius*scaleRadius, 0);

Журналы: Всегда тот же коэффициент, что радиус не должен двигаться, потому что мой палец остановлен

2020-03-27 15:42:56.113 onTouch: scaleRadius 1.7870371
2020-03-27 15:42:56.113 onTouch: scaleRadius 1.7870373
2020-03-27 15:42:56.227 onTouch: scaleRadius 1.7870371
2020-03-27 15:42:56.227 onTouch: scaleRadius 1.7870373
2020-03-27 15:42:56.331 onTouch: scaleRadius 1.7870374
2020-03-27 15:42:56.331 onTouch: scaleRadius 1.7870371

1 Ответ

1 голос
/ 25 марта 2020

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

Я буду предполагать, что centerX и centerY всегда являются одним и тем же значением и в основном являются глобальными переменными.

Создаем пару дополнительных глобальных переменные:

boolean animIsCurrentlyPlaying=false; 
float mCurrentRadius=initialCircleSize; //i guess this is 1 in your case
float mTargetRadius; 

Теперь для события ACTION_MOVE вы будете делать следующее:

1 - установите mTargetRadius в качестве некоторой функции расстояния между centerX и centerY и положение пальца на экране (в качестве примера можно привести евклидово расстояние);

mTargetRadius=Float.valueOf(Math.sqrt((double)(Math.pow(event.getX()-centerX,2)+Math.pow(event.getY()-centerY,2))));

2 - приведен следующий метод revealModified(view, 100);

public void revealModified(final View view,
                           final int duration) {
       if(!animIsCurrentlyPlaying){
            //here i just reference the global vars
            anim = ViewAnimationUtils.createCircularReveal(view, centerX, centerY, mCurrentRadius, mTargetRadius);
            mCurrentRadius=mTargetRadius;
            anim.setDuration(duration);
            anim.addListener(new Animator.AnimatorListener() {

                @Override
                public void onAnimationEnd(Animator animation) {

                    animIsCurrentlyPlaying=false;
                    if(mCurrentRadius!=mTargetRadius){
                         revealModified(view, 100);
                    }
                }

            });
            animIsCurrentlyPlaying=true;
            anim.start();
       }

}

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

дайте мне знать, если это работает, и особенно если это то, что вы хотели

...