简体   繁体   English

圆形显示动画 onTouch Android

[英]Circular Reveal animation onTouch Android

I'm trying to implement a circular reveal animation which consist to reveal the view according the user finger when he's touching the view.我正在尝试实现一个圆形显示动画,其中包括在用户触摸视图时根据用户手指显示视图。

First, my view is inside an infinite circular reveal loop to keep the rounded aspect as long as the user do nothing.首先,我的视图位于一个无限循环显示循环内,只要用户什么都不做,就可以保持圆形外观。 Then when the user touch the view and start to swipe I calculated a factor inside the ACTION_MOVE to increase the radius in real time and call the circular reveal at each pass.然后当用户触摸视图并开始滑动时,我计算了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();

    }

I recall the circular reveal method again inside its Listener to create the loop and the most important to avoid visual distortion.我再次回忆起它的 Listener 中的循环显示方法来创建循环,最重要的是避免视觉失真。

I have noticed that if I didn't do this way some very fast distortion showed up because the animation duration is faster than each pass in ACTION_MOVE so the anim have time to finish before the next pass.我注意到,如果我不这样做,会出现一些非常快的失真,因为动画持续时间比ACTION_MOVE每次传递ACTION_MOVE因此动画有时间在下一次传递之前完成。 The distortion is the representation of the missing part of the view when the animation is finished and came back very fast to the current radius set with the Touch like a flash.失真是动画完成后视图中缺失部分的表示,并像闪光一样快速返回到使用 Touch 设置的当前半径。

So this way with the method recall inside the Listener is working great until there.因此,在侦听器内部调用方法的这种方式在那里工作得很好。

Problem : On one of my devices there are senseless distortion in all directions while swiping.问题:在我的其中一台设备上滑动时,各个方向都出现了无意义的失真。

在此处输入图片说明

According to my logs it's not a radius distortion because the start and end radius is always the same after each pass so the radius should not be moving like this especially when the finger is stopped, and the animation never stop thanks to the Listener like I explained above.根据我的日志,这不是半径失真,因为每次通过后开始和结束半径始终相同,因此半径不应该像这样移动,尤其是当手指停止时,动画永远不会停止,这要归功于我解释的 Listener以上。

What am I doing wrong ?我究竟做错了什么 ?

I searched a lot and didn't find the same problem so I tried other ways like drawing canvas but unfortunately it doesn't match with my needs.我搜索了很多,没有发现同样的问题,所以我尝试了其他方法,比如画画布,但不幸的是它不符合我的需求。

Is there another way to achieve this kind of animation even completely differently ?有没有另一种方法可以完全不同地实现这种动画?

Any lead is appreciate thanks in advance提前感谢任何线索

EDIT : inside the ACTION_MOVE编辑:ACTION_MOVE里面

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

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

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

Logs : Always the same factor then the radius should not move because my finger is stopped日志:总是相同的因素,那么半径不应该移动,因为我的手指停止了

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

I am assuming that you dont want the flickering animation but rather that the radius of your circe transitions smoothly and becomes either bigger or smaller as a function of how far you swipe on the screen.我假设您不想要闪烁的动画,而是希望圆的半径平滑过渡并根据您在屏幕上滑动的距离而变大或变小。 (please correct me if this assumption is wrong) (如果这个假设是错误的,请纠正我)

I will assume that centerX and centerY are always the same value and are basically global variables.我将假设centerXcenterY总是相同的值并且基本上是全局变量。

Create a couple of additional global variables:创建几个额外的全局变量:

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

Now on the ACTION_MOVE event you will do the following:现在在ACTION_MOVE事件中,您将执行以下操作:

1- set mTargetRadius to be some function of the distance between centerX and centerY and the position of the finger on the screen (euclidean distance might be a good pick here is an example); 1-将mTargetRadius设置为centerXcenterY之间的距离以及手指在屏幕上的位置的一些函数(欧氏距离可能是一个很好的选择,这里是一个例子);

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

2- excecute the following method revealModified(view, 100); 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();
       }

}

the method will be excecuted every time you move your finger ever so slightly.每次您稍微移动手指时,都会执行该方法。 I set the duration to 100 ms but that can be shorter if you find its not reactive enough.我将持续时间设置为 100 毫秒,但如果您发现它的反应性不够,则可以更短。 anytime you move your finger a flag is set so no other animations can be started on top and the transition is always smooth.if you move your finger while an anim is playing then revealModified will be reexecured in the if statement within onAnimationEnd.任何时候你移动你的手指一个标志被设置成没有其他动画可以在上面启动和过渡总是smooth.if你移动你的手指,而一个动画播放,然后revealModified将内onAnimationEnd if语句来reexecured。

let me know if it works and especially if this is what you wanted让我知道它是否有效,尤其是如果这是你想要的

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM