我试图将视图从开始矩形(例如由另一个视图定义)缩放到它的最终位置。
我尝试使用以下代码来设置直观的动画:
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));
animatedView
是RelativeLayout
的子项(布局参数设置为布局的某些标题视图下方),测量的宽度,高度和位置是动画设置时的有效值。
根据startRect
我观察到不同的动画 - 有时动画视图显示在startRect
的下方或上方。
似乎RectEvaluator是可能的解决方案之一,但它只能从API 18获得。
从开始矩形位置到最终位置(未修改的位置)动画视图的正确方法是什么?
答案 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));
}
}