简体   繁体   English

在Android中为矩形动画的最佳方法

[英]Best way to animate rectangle in Android

I want to animate a rectangle filled with one opaque color. 我想为填充了一种不透明颜色的矩形设置动画。 The attributes I will be animating is the translation, and the width of the active menu item. 我要设置动画的属性是转换以及活动菜单项的宽度。

I know how to animate things, but in this case, I want it to do no layouts on the view, since my animation will occur inside a LinearLayout, and it will not exceed it's size. 我知道如何为事物设置动画,但是在这种情况下,我希望它在视图上不做任何布局,因为我的动画将出现在LinearLayout中,并且不会超过其大小。

The Blue line on top of my layout is what I will be animating. 我将在动画上方显示蓝线。 It will go horizontally to the left and right, while changing it's width, so that it fits on the selected menu item. 更改宽度时,它将水平左右移动,以适合所选菜单项。

在此处输入图片说明

I usually work with animations on the margin, but it consumes a lot of processing to re-calculate bounds on the layout process. 我通常在边缘上处理动画,但是它需要大量的处理才能重新计算布局过程中的边界。

Any suggestions on how to do that? 有什么建议吗?

That depends entirely on what API level you're targetting, if you're only targeting >3.0 then ObjectAnimator and ValueAnimator or the nicer ViewPropertyAnimator are your best friend, they let you do simple things like "move the X value of this 100dp while increasing the width by a factor of two, in 300ms". 这完全取决于您要定位的API级别,如果您仅定位> 3.0,那么ObjectAnimator和ValueAnimator或更好的ViewPropertyAnimator是您最好的朋友,它们可以让您做一些简单的事情,例如“在增加100dp的同时移动X值宽度的两倍,以300ms为单位。

If you're targeting a lower API level check out NineOldAndroids which brings that functionality over to all versions of Android. 如果您的目标是较低的API级别,请查看NineOldAndroids ,它将该功能引入所有版本的Android。

To do what you want to do it'd be something along the lines of: 要执行您想做的事情,可能需要遵循以下步骤:

myImageView.scaleXBy(FACTOR_NEEDED_FOR_NEW_WIDTH);

and that's all to it. 仅此而已。

As a sidenote: It looks like you might be attempting to replicate a ViewPager 's indicator, in which case you should be using an actual indicator. 附带说明:您似乎正在尝试复制ViewPager的指标,在​​这种情况下,您应该使用实际的指标。

I had to animate the Margin and the Width of the view, because there was no way out, since I'm using android version >=8. 我必须设置视图的边距和宽度的动画,因为没有出路,因为我使用的是Android版本> = 8。

Here is my two classes that can do this: 这是我的两个班可以做到的:

MarginAnimation class: MarginAnimation类:

public class MarginAnimation extends Animation{// implements AnimationListener{
    public static String TAG = "MarginAnimation";

    protected View animatingView;

    protected int fromMarginLeft = 0;
    protected int fromMarginTop = 0;

    protected int toMarginLeft = 0;
    protected int toMarginTop = 0;

    protected LayoutParams layoutParam;

    public MarginAnimation(View v, int toMarginLeft, int toMarginTop) {
        this.toMarginLeft = toMarginLeft;
        this.toMarginTop = toMarginTop;

        this.animatingView = v;

        // Save layout param
        layoutParam = (LayoutParams) animatingView.getLayoutParams();

        // Save current margins as initial state
        saveCurrent();

        // Set the listner to be self object
//      setAnimationListener(this);
    }

    public MarginAnimation(View v, int fromMarginLeft, int toMarginLeft, int fromMarginTop, int toMarginTop) {
        this.fromMarginLeft = fromMarginLeft;
        this.toMarginLeft = toMarginLeft;

        this.fromMarginTop = fromMarginTop;
        this.toMarginTop = toMarginTop;

        this.animatingView = v;

        // Save layout param
        layoutParam = (LayoutParams) animatingView.getLayoutParams();

        // Set the listner to be self object
//      setAnimationListener(this);
    }

    protected void saveCurrent(){
        fromMarginLeft = layoutParam.leftMargin;
        fromMarginTop  = layoutParam.topMargin;
    }

    long lastTime = 0;

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
//      long thisTime = System.nanoTime();

//      if(lastTime != 0)
//          Log.e(TAG, ((thisTime - lastTime) / 1000) + "delta Anim.");

//      lastTime = thisTime;

        layoutParam.leftMargin = (int)(fromMarginLeft + (toMarginLeft - fromMarginLeft) * interpolatedTime);
        layoutParam.topMargin = (int)(fromMarginTop + (toMarginTop- fromMarginTop) * interpolatedTime);
        animatingView.setLayoutParams(layoutParam);
    }

    @Override
    public boolean willChangeBounds() {
        return false;
    }
}

MarginAndWidthAnimation class: MarginAndWidthAnimation类:

public class MarginAndWidthAnimation extends MarginAnimation{
    public static String TAG = "MarginAndWidthAnimation";

    int toWidth;
    int fromWidth;

    public MarginAndWidthAnimation(View v, int toMarginLeft, int toMarginTop, int toWidth) {
        super(v, toMarginLeft,toMarginTop);

        this.toWidth = toWidth;

//      Log.i(TAG, "++F: "+this.fromWidth+" T: "+this.toWidth);
    }

    protected void saveCurrent(){
        super.saveCurrent();
//      fromWidth = animatingView.getWidth();
        fromWidth = layoutParam.width;
//      Log.i(TAG, "F: "+fromWidth+" T: "+toWidth);
    }

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {

        layoutParam.width = (int)(fromWidth + (toWidth - fromWidth) * interpolatedTime);
//      Log.i(TAG, "F: "+fromWidth+" T: "+toWidth+" S: "+layoutParam.width);
        super.applyTransformation(interpolatedTime, t);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM