【问题标题】:Circular Reveal animation onTouch AndroidCircular Reveal 动画 onTouch Android
【发布时间】:2020-03-17 18:28:53
【问题描述】:

我正在尝试实现一个圆形显示动画,该动画包括在用户触摸视图时根据用户手指显示视图。

首先,我的视图位于无限循环显示循环中,只要用户什么都不做,就可以保持圆形外观。 然后当用户触摸视图并开始滑动时,我计算了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();

    }

我再次回忆起它的 Listener 中的循环显示方法来创建循环,并且最重要的是避免视觉失真。

我注意到,如果我不这样做,就会出现一些非常快速的失真,因为动画持续时间比ACTION_MOVE 中的每次传递都快,因此动画有时间在下一次传递之前完成。 失真是动画完成后视图缺失部分的表示,并像闪光灯一样快速返回到使用 Touch 设置的当前半径。

因此,在侦听器中调用方法的这种方式在此之前工作得很好。

问题: 在我的一台设备上,滑动时各个方向都有无意义的失真。

根据我的日志,这不是半径失真,因为每次通过后开始和结束半径始终相同,因此半径不应该像这样移动,尤其是当手指停止时,并且动画永远不会停止,这要归功于 Listener就像我上面解释的那样。

我做错了什么?

我搜索了很多,没有发现同样的问题,所以我尝试了其他方法,比如绘制画布,但不幸的是它不符合我的需求。

还有其他方法可以完全不同地实现这种动画吗?

提前感谢任何线索

编辑: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

【问题讨论】:

  • 听起来很有趣,您能否透露更多代码,以查看您为方法提供的输入以及您注册滑动操作的位置。一个 GIF 或视频也有助于更好地理解和思考替代方案。
  • 是否有可能在动画运行时使用旧值执行显示方法,然后在动画结束时再次执行?您是否尝试过在每个视图上同步该方法?现在只是猜测
  • 我认为这些值不是问题,因为我在 startRadius 和 endRadius 内部设置了相同的值,所以圆不会因为值而扭曲。如果我告诉你的是错误的,数学会导致我得到的不同的失真
  • 我正在考虑一个替代方案,因为我现在无法修复它,也无法修改谷歌的动画。奇怪的一面是它只在我的设备的 1/10 上。当我知道如何分享视频时,我会尝试提供视频
  • 我觉得最简单的方法是把它做成一个gif,然后你就可以像图片一样上传了

标签: android animation touch move circularreveal


【解决方案1】:

我假设你不想要闪烁的动画,而是你的圆的半径平滑过渡,并且随着你在屏幕上滑动的距离而变大或变小。 (如果这个假设是错误的,请纠正我)

我会假设centerXcenterY 总是相同的值并且基本上是全局变量。

创建几个额外的全局变量:

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

现在在ACTION_MOVE 活动中,您将执行以下操作:

1- 将mTargetRadius 设置为centerXcenterY 之间的距离以及手指在屏幕上的位置的某个函数(欧几里得距离可能是一个很好的选择,这里是一个例子);

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 将在 onAnimationEnd 内的 if 语句中重新执行。

让我知道它是否有效,尤其是如果这是你想要的

【讨论】:

  • 你的构想是有效的
  • 嗯,已尝试添加一些日志。例如,您从屏幕 motionEvent.getX() 得到什么输入。
  • 。顺便说一句,那是什么设备。还要在revealmodified中放一些日志来查看函数的半径输入值
  • 在我看来,这可能是来自该特定设备的奇怪输入。使用我的代码后,闪烁是否有任何变化,是更糟还是不同?
  • 没有改变任何东西,我正在寻找替代方案
猜你喜欢
  • 2020-08-14
  • 1970-01-01
  • 2014-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多