【问题标题】:How do I make a smooth animation with ValueAnimator?如何使用 ValueAnimator 制作流畅的动画?
【发布时间】:2020-01-28 19:12:35
【问题描述】:

我想在使用动画单击扩展 fab 时隐藏它。我想将按钮从原始高度和宽度缩小到 0/gone。它消失在角落,但动画在中间滞后。

    private fun animateHideScoreFab(){
        val animX = ValueAnimator.ofInt(editScoreFab.measuredWidth, 0).apply {
            duration = 1000
        }
        val animY = ValueAnimator.ofInt(editScoreFab.measuredHeight, 0).apply {
            duration = 1000
        }


        animX.addUpdateListener {
            val value = it.animatedValue as Int
            editScoreFab.layoutParams.width = value
            editScoreFab.requestLayout()
        }

        animY.addUpdateListener {
            val value = it.animatedValue as Int
            editScoreFab.layoutParams.height = value
        }

        AnimatorSet().apply {
            this.interpolator = AccelerateDecelerateInterpolator()
            play(animX).with(animY)
            start()
        }

    }

结果:

【问题讨论】:

  • 在我看来,动画看起来“不流畅”也是因为文本在可绘制对象之前消失了。除此之外,drawable 的 padding 也减少了,因此 drawable 的移动速度比 Button 边缘慢。也许一个人可以分两步完成?先淡出文字和drawable再缩小Button?

标签: android animation material-design


【解决方案1】:

使用AccelerateDecelerateInterpolator https://developer.android.com/reference/android/view/animation/AccelerateDecelerateInterpolator 表示

变化率开始和结束缓慢但在中间加速的插值器。

所以中间的变化速度比开始的快,这可能使它看起来滞后

尝试其他插值器,例如具有恒定变化率的 LinearInterpolator https://developer.android.com/reference/android/view/animation/LinearInterpolator.html

更新 对于 AccelerateDecelerateInterpolator,如果您在 400 毫秒和 600 毫秒之间查看 https://developer.android.com/guide/topics/graphics/prop-animation.html#interpolators 中的表格,则该值会跳跃您和动画距离的 45.5%

平滑的另一个因素是不使用 Int 而是使用 Float,例如ValueAnimator.ofFloat 所以它有中间步骤,

更新2

重新布置一个项目的成本很高,因为它必须被测量和重新绘制。

缩放已经绘制的图像应该更快更流畅,因为这通常由 GPU 完成,因此更快更流畅。缩放视图也需要Float

将 Fab 缩放到右上角的示例 onClick(注意使用 ObjectAnimator,因为它更易于实现)

对不起,Java 不是 Kotlin

        FloatingActionButton fab = findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                AnimatorSet animationSet = new AnimatorSet();

                // Set point to scale around to top right
                view.setPivotY(0);
                view.setPivotX(view.getMeasuredWidth());

                ObjectAnimator scaleY = ObjectAnimator.ofFloat(view,"scaleY", 1f, 0f);
                scaleY.setDuration(1000);
                // Optional as AccelerateDecelerateInterpolator is the default
                scaleY.setInterpolator(new AccelerateDecelerateInterpolator());
                ObjectAnimator scaleX = ObjectAnimator.ofFloat(view,"scaleX", 1f, 0f);
                scaleX.setDuration(1000);
                // Optional as AccelerateDecelerateInterpolator is the default
                scaleX.setInterpolator(new AccelerateDecelerateInterpolator());
                animationSet.playTogether(scaleX, scaleY);
                animationSet.start();
            }
        });

【讨论】:

  • 我尝试了 LinearInterpolator,但遇到了同样的问题。我同意它应该是一个浮点数,但视图的高度和宽度采用 Int 作为值。
  • 给出缩放视图而不是重新布置按钮的示例,这样做非常昂贵。
【解决方案2】:

在 Views 中有一个 scaleXscaleY 属性,您可以从 1 到 0 进行插值,这将产生 View 缩小而不是容器缩小的效果。

其次,如果您的父布局参数不适合您,则要将缩放动画工作到顶部,您必须将枢轴设置为 rightXtop 角:view.pivotX = view.width; view.pivotY = 0

另外,如果您使用 propertyListener 并自己更新它,您可以只使用一个 ValueAnimator 并自己进行计算,并考虑将 editScoreFab.requestLayout() 替换为 editScoreFab.invalidate()

【讨论】:

    猜你喜欢
    • 2018-11-26
    • 1970-01-01
    • 2015-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-27
    • 2014-01-16
    • 1970-01-01
    相关资源
    最近更新 更多