View-属性动画

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ZmeSky/article/details/81300782
android中动画一共有三种
1.帧动画
2.View动画
3.属性动画
由于前面两个动画有一定的局限性,android3.0之后,谷歌推出了新的动画框架,帮助开发者实现更加丰富的动画效果。
在Animator框架中使用最多的就是AnimatorSet和ObjectAnimator配合:使用ObjectAnimator进行更精细化的控制,控制一个对象和一个属性值,而使用多个ObjectAnimator组合到AnimatorSet形成一个动画。属性动画通过调用属性的get,set方法来真实的控制一个View的属性值,因此强大的属性动画框架基本可以实现所有的动画效果。
1.ObjectAnimator
ObjectAnimator是属性动画最重要的类,参数包括View对象和对象的属性名称,这个属性名称必须有get和set方法,其内部会通过Java反射机制来调用set方法修改对象的属性值。
ObjectAnimator.ofFloat(customView,"translationX",0,300).setDuration(1000).start();

ofFloat()方法源码如下:

public static ObjectAnimator ofFloat(Object target, String propertyName, float... values) {
    ObjectAnimator anim = new ObjectAnimator(target, propertyName);
    anim.setFloatValues(values);
    return anim;
}
常用的属性动画的属性值:
translationX,translationY:用来沿着X轴或者Y轴进行平移。
rotation rotationX rotationY:用来围绕View的支点进行旋转。
PrivotX和PrivotY:控制View对象的支点位置。默认支点位置是View的中心点。
alpha:透明度,默认是1(不透明),0代表完全透明。
x和y:描述View对象在其容器中的最终位置。

需要注意的是,使用ObjectAnimator时,属性必须要有get和set方法,否则是不会生效的。在自定义View里我们可以自己写一些包装getset方法的操作。

public void setWidth(int width){
    target.getLayoutParams().width = width;
    target.requestLayout();
}
public int getWidth(){
    return  target.getLayoutParams().height;
}
这样可以通过调用属性,间接的达到动画效果。
ObjectAnimator.ofFloat(customView,"width",0,300).setDuration(1000).start();

2.ValueAnimator
ValueAnimator不提供任何动画效果,从字面意思就可以看出,这是一个动画数值变化的过程。
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0,300);
valueAnimator.setDuration(1000);
valueAnimator.setTarget(customView);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        float ft = (float) animation.getAnimatedValue();
    }
});
valueAnimator.start();

3.动画的监听
完整的动画具有start,repeat,end,cancel 4个过程。
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(customView,"translationX",0,300);
objectAnimator.setDuration(1000).start();
objectAnimator.addListener(new Animator.AnimatorListener() {
    @Override
    public void onAnimationStart(Animator animation) {
        
    }
    @Override
    public void onAnimationEnd(Animator animation) {

    }
    @Override
    public void onAnimationCancel(Animator animation) {

    }
    @Override
    public void onAnimationRepeat(Animator animation) {

    }
});
大部分时候我们只关心onAnimationEnd动画结束事件,Android也提供了AnimatorListenterAdapter来让我们选择必要的事件进行监听。
objectAnimator.addListener(new AnimatorListenerAdapter() {
    @Override
    public void onAnimationEnd(Animator animation) {
        super.onAnimationEnd(animation);
    }
});

4.组合动画 AnimatorSet
AnimatorSet类提供了一个play()方法,如果我们向这个方法中传入一个Animator对象,将会返回一个AnimatorSet.Builder的实例。
play()源码:
public Builder play(Animator anim) {
    if (anim != null) {
        return new Builder(anim);
    }
    return null;
}
在方法里创建了Builder对象,Builder类源码:
public class Builder {

    /**
     * This tracks the current node being processed. It is supplied to the play() method
     * of AnimatorSet and passed into the constructor of Builder.
     */
    private Node mCurrentNode;

    /**
     * package-private constructor. Builders are only constructed by AnimatorSet, when the
     * play() method is called.
     *
     * @param anim The animation that is the dependency for the other animations passed into
     * the other methods of this Builder object.
     */
    Builder(Animator anim) {
        mDependencyDirty = true;
        mCurrentNode = getNodeForAnimation(anim);
    }

    /**
     * Sets up the given animation to play at the same time as the animation supplied in the
     * {@link AnimatorSet#play(Animator)} call that created this <code>Builder</code> object.
     *
     * @param anim The animation that will play when the animation supplied to the
     * {@link AnimatorSet#play(Animator)} method starts.
     */
    public Builder with(Animator anim) {
        Node node = getNodeForAnimation(anim);
        mCurrentNode.addSibling(node);
        return this;
    }

    /**
     * Sets up the given animation to play when the animation supplied in the
     * {@link AnimatorSet#play(Animator)} call that created this <code>Builder</code> object
     * ends.
     *
     * @param anim The animation that will play when the animation supplied to the
     * {@link AnimatorSet#play(Animator)} method ends.
     */
    public Builder before(Animator anim) {
        Node node = getNodeForAnimation(anim);
        mCurrentNode.addChild(node);
        return this;
    }

    /**
     * Sets up the given animation to play when the animation supplied in the
     * {@link AnimatorSet#play(Animator)} call that created this <code>Builder</code> object
     * to start when the animation supplied in this method call ends.
     *
     * @param anim The animation whose end will cause the animation supplied to the
     * {@link AnimatorSet#play(Animator)} method to play.
     */
    public Builder after(Animator anim) {
        Node node = getNodeForAnimation(anim);
        mCurrentNode.addParent(node);
        return this;
    }

    /**
     * Sets up the animation supplied in the
     * {@link AnimatorSet#play(Animator)} call that created this <code>Builder</code> object
     * to play when the given amount of time elapses.
     *
     * @param delay The number of milliseconds that should elapse before the
     * animation starts.
     */
    public Builder after(long delay) {
        // setup dummy ValueAnimator just to run the clock
        ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
        anim.setDuration(delay);
        after(anim);
        return this;
    }
}
Builder类采用了建造者模式,它有4个方法,用来控制动画的播放顺序:
after(Animator anim):将现有动画插入到传入的动画之后执行。
after(long delay):将现有动画延迟指定的毫秒后执行。
before(Animator anim):将现有动画插入到传入的动画的之前执行。
with(Animator anim):将现有动画和传入动画同时执行。

AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(animator1).with(animator2).after(animator3);
这里animator1和animator2是同时执行动画,又指定在animator3之后执行,所以执行顺序是animator3先执行动画后,animator1和animator2后面同时执行。
5.组合动画 PropertyValuesHolder
除了上面的AnimatorSet类,还可以用PropertyValuesHolder类来实现组合动画。不过这个组合动画就没有AnimatorSet丰富,只能是多个动画一起执行。
PropertyValuesHolder holder1 = PropertyValuesHolder.ofFloat("translationX",0,300);
PropertyValuesHolder holder2 = PropertyValuesHolder.ofFloat("alpha",1.0f,0.3f,1.0f);
ObjectAnimator.ofPropertyValuesHolder(customView,holder1,holder2).setDuration(2000).start();

6.在XML中使用属性动画
和View动画一样,属性动画也可以直接写在xml中,在res文件中新建animator文件夹,创建xml文件。
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000" android:fillAfter="true">
    <propertyValuesHolder android:propertyName="scaleX" android:valueFrom="1.0" android:valueTo="3.0"/>
</objectAnimator>
调用方式:
Animator animator = AnimatorInflater.loadAnimator(this,R.animator.scale);
animator.setTarget(customView);
animator.setDuration(1000);
animator.start();

猜你喜欢

转载自blog.csdn.net/ZmeSky/article/details/81300782