2017-02-18 148 views
0

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

我试图用下面的代码来设置动画看起来直截了当:

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

什么是动画从开始的矩形位置以最终(没有修改的)的正确方法?

+2

使用'android.animation.RectEvaluator' – pskink

+0

@pskink看起来很有希望。我是否应该使用翻译和缩放属性在每个步骤上应用结果矩形? – sandrstar

+1

请参阅http://pastebin.com/jaXTjGjA – pskink

回答

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)); 
    } 
} 
相关问题