从开始矩形到最终位置缩放

时间:2017-02-18 14:35:33

标签: android objectanimator

我试图将视图从开始矩形(例如由另一个视图定义)缩放到它的最终位置。

我尝试使用以下代码来设置直观的动画:

float scaleX = 0f;
float scaleY = 0f;
Rect startRect = new Rect(10, 10, 100, 100); // taken from real view position with getLocationOnScreen
final Collection<Animator> animators = new ArrayList<>();

if (animatedView.getMeasuredHeight() != 0) {
    scaleX = (float)startRect.width() / animatedView.getMeasuredWidth();
}

if (animatedView.getMeasuredHeight() != 0) {
    scaleY = (float)startRect.height() / animatedView.getMeasuredHeight();
}

animatedView.getLocationInWindow(location);
animatedView.setPivotX(startRect.left);
animatedView.setPivotY(startRect.top);
animatedView.setScaleX(scaleX);
animatedView.setScaleY(scaleY);

animators.add(ObjectAnimator.ofFloat(animatedView, View.SCALE_X, 1.0f).setDuration(1000));
animators.add(ObjectAnimator.ofFloat(animatedView, View.SCALE_Y, 1.0f).setDuration(1000));

animatedViewRelativeLayout的子项(布局参数设置为布局的某些标题视图下方),测量的宽度,高度和位置是动画设置时的有效值。

根据startRect我观察到不同的动画 - 有时动画视图显示在startRect的下方或上方。

似乎RectEvaluator是可能的解决方案之一,但它只能从API 18获得。

从开始矩形位置到最终位置(未修改的位置)动画视图的正确方法是什么?

1 个答案:

答案 0 :(得分:0)

根据对该问题的评论,可以从Android源代码复制RectEvaluator代码,然后应用以下逻辑:

RectViewAnimator mRectAnimator;

/**
 * Creates animator which can be played. From some start position
 * to final (real position).
 * From final position to start position can be achieved using reverse interpolation.
 */
private Collection<Animator> createMoveAnimators(View targetView, Rect startRect) {
    final Collection<Animator> animators = new ArrayList<>();
    final int[] location = new int[2];

    targetView.getLocationOnScreen(location);

    final Rect finalRect = new Rect(location[0], location[1],
            location[0] + targetView.getMeasuredWidth(),
            location[1] + targetView.getMeasuredHeight());

    // Must keep this reference during animations, since Animator keeps only WeakReference to it's targets.
    mRectAnimator = appendRectEvaluatorAnimation(animators, targetView, 500, startRect, finalRect);

    return animators;
}

private RectViewAnimator appendRectEvaluatorAnimation(final Collection<Animator> animators, final View view, final int duration,
                                                      final Rect startRect, final Rect finalRect) {
    final float scaleX = (float) startRect.width() / finalRect.width();
    final float scaleY = (float) startRect.height() / finalRect.height();

    view.setTranslationY(startRect.top - (finalRect.top + (1 - scaleY) * finalRect.height() / 2));
    view.setTranslationX(startRect.left - (finalRect.left + (1 - scaleX) * finalRect.width() / 2));
    view.setScaleX(scaleX);
    view.setScaleY(scaleY);

    final RectViewAnimator rectViewAnimator = new RectViewAnimator(view, finalRect);
    final Animator animator = ObjectAnimator.ofObject(rectViewAnimator, RectViewAnimator.RECT,
            new RectEvaluator(), startRect, finalRect);

    animators.add(animator);
    return rectViewAnimator;
}

private static class RectViewAnimator {
    static final String RECT = "rect";

    private final View target;
    private final Rect finalRect;

    RectViewAnimator(final View target, final Rect finalRect) {
        this.target = target;
        this.finalRect = finalRect;
    }

    @Keep
    public void setRect(final Rect r) {
        final float scaleX = (float)r.width() / finalRect.width();
        final float scaleY = (float)r.height() / finalRect.height();

        target.setScaleX(scaleX);
        target.setScaleY(scaleY);
        target.setTranslationX(r.left - (finalRect.left + (1 - scaleX) * finalRect.width() / 2));
        target.setTranslationY(r.top - (finalRect.top + (1 - scaleY) * finalRect.height() / 2));
    }
}