在项目开发中,根据需求会有一些动画的效果,在android3.0之前的就有补间动画(Tween Animation)和帧动画(Frame Animation),但是实现的效果有限,android3.0之后就出现了属性动画(Property Animation),属性动画更改的是View实际的属性,所以不会影响其在动画执行后所在位置的正常使用。

属性动画常用api:

ObjectAnimator :对象动画执行类。
PropertyValuesHolder : 属性存储器,为两个执行类提供更新多个属性的功能。
AnimatorListener :动画执行监听,在动画开始、重复、结束、取消时进行回调。
Keyframe :为 PropertyValuesHolder提供多个关键帧的操作值。
AnimatorSet :一组动画的执行集合类:设置执行的先后顺序,时间等。
TimeInterpolator :时间插值,用于控制动画执行过程。
ValueAnimator :值动画执行类,常配合AnimatorUpdateListener使用。
AnimatorUpdateListener :动画更新监听。
TypeEvaluator :类型估值,用于设置复杂的动画操作属性的值。

属性动画插值器:

android 属性动画缩放后布局在父布局左下角_插值器

android 属性动画缩放后布局在父布局左下角_animation动画详解_02


AccelerateDecelerateInterpolator :加速减速插值器

android 属性动画缩放后布局在父布局左下角_属性动画_03


AccelerateInterpolator :加速插值器

android 属性动画缩放后布局在父布局左下角_animation动画详解_04


AnticipateInterpolator :回荡秋千插值器

android 属性动画缩放后布局在父布局左下角_android_05


BounceInterpolator :弹跳插值器

android 属性动画缩放后布局在父布局左下角_插值器_06


CycleInterpolator :正弦周期变化插值器

android 属性动画缩放后布局在父布局左下角_android_07


DecelerateInterpolator :减速插值器

android 属性动画缩放后布局在父布局左下角_插值器_08


AnticipateOvershootInterpolator :开始的时候向后然后向前甩一定值后返回最后的值

android 属性动画缩放后布局在父布局左下角_android_09


OvershootInterpolator:向前甩一定值后再回到原来位置

属性动画的设置:

1)translationX 和 translationY:这两个属性控制了View所处的位置,它们的值是由layout容器设置的,是相对于坐标原点(0,0左上角)的一个偏移量。
2)rotation, rotationX 和 rotationY:控制View绕着轴点(pivotX和pivotY)旋转。
3)scaleX 和 scaleY:控制View基于pivotX和pivotY的缩放。
4)pivotX 和 pivotY:旋转的轴点和缩放的基准点,默认是View的中心点。
5)x 和 y:描述了view在其父容器中的最终位置,是左上角左标和偏移量(translationX,translationY)的和。
6)aplha:透明度,1是完全不透明,0是完全透明。

translationX 和 translationY:

private void startAnimationVaule(View view){
    //X平移动画
    ObjectAnimator oa = ObjectAnimator.ofFloat(view, "translationX", 0f, 300f);
    oa.setDuration(500);
    oa.start();
    //Y平移动画
    ObjectAnimator ob=ObjectAnimator.ofFloat(view,"translationY",0f,300f);
    ob.setDuration(500);
    ob.start();
}

android 属性动画缩放后布局在父布局左下角_android 3.0_10

如果想添加插值器,在start之前设置相应的插值器就可以了;

rotationX 和 rotationY:

//X翻转动画
ObjectAnimator oc=ObjectAnimator.ofFloat(view,"rotationX",0f,360f);
oc.setDuration(500);
oc.start();

android 属性动画缩放后布局在父布局左下角_android 3.0_11

scaleX 和 scaleY:

//X缩放
ObjectAnimator scaleX = ObjectAnimator.ofFloat(iv, "scaleX", 1f, 0.5f);
scaleX.setDuration(500);
scaleX.start();

android 属性动画缩放后布局在父布局左下角_android_12

aplha:

//透明度动画
ObjectAnimator scaleX = ObjectAnimator.ofFloat(iv, "alpha", 1f, 0.5f);
scaleX.setDuration(500);
scaleX.start();

android 属性动画缩放后布局在父布局左下角_属性动画_13

在项目开发中可能不只是单个属性动画的时候,可能会涉及到多个动画的同时使用,对于多个动画同时执行的方式有很多种:

方式一:

private void startMoreAnimationSecond(View view){
    //如果没有这个属性的时候,就默认valueanimator
    ObjectAnimator haha = ObjectAnimator.ofFloat(view, "haha", 0f, 100f);
    haha.setDuration(300);
    //设置监听动画
    haha.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            //动画在执行的过程中,不断的调用此方法
            Float animatedValue = (Float) animation.getAnimatedValue();
            //X翻转
            iv.setScaleX(0.5f+animatedValue/200);
            //Y翻转
            iv.setScaleY(0.5f+animatedValue/200);
        }
    });
    //开启动画
    haha.start();
}

方式二:

private void startMoreAnimationThrid(View view){
    ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f, 200f);
    valueAnimator.setDuration(200);
    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            Float animatedValue = (Float) animation.getAnimatedValue();
            iv.setScaleX(0.5f+animatedValue/200);
            iv.setScaleY(0.5f+animatedValue/200);
        }
    });
    valueAnimator.start();
}

方式三:

private void startMoreAnimationFour(View view){
    //透明度动画
    PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1f, 0.7f, 1f);
    //X缩放
    PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 1f, 0.7f, 1f);
    //Y缩放
    PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 1f, 0.7f, 1f);
    //X平移
    PropertyValuesHolder translationX = PropertyValuesHolder.ofFloat("translationX", 0f, 300f);

    ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(iv, alpha, scaleX, scaleY, translationX);
    objectAnimator.setDuration(1000);
    objectAnimator.start();
}

android 属性动画缩放后布局在父布局左下角_animation动画详解_14

方式四:

private void startMoreAnimationFive(View view){
    //透明度动画
    ObjectAnimator alpha = ObjectAnimator.ofFloat(iv, "alpha", 1f, 0.7f, 1f);
    //X缩放
    ObjectAnimator scaleX = ObjectAnimator.ofFloat(iv, "scaleX", 1f, 0.7f, 1f);
    //Y缩放
    ObjectAnimator scaleY = ObjectAnimator.ofFloat(iv, "scaleY", 1f, 0.7f, 1f);
    //动画集合
    AnimatorSet set=new AnimatorSet();
    set.setDuration(500);
    //同时执行动画
//  set.playTogether(alpha,scaleX,scaleY);
    //依次执行动画
    set.playSequentially(alpha,scaleX,scaleY);
    set.start();

}

属性动画仿淘宝产品(IOS)详情动画效果:

android 属性动画缩放后布局在父布局左下角_android 3.0_15

这个效果涉及到几个属性动画的同时使用和执行;
第一个view:翻转动画、透明度动画、缩放动画、平移动画
第二个view:平移动画

private void setAnimator(final boolean isFrist){
    float fristValue=0;
    float secondValue=0;
    //frist 1 翻转动画  2透明度动画  3缩放动画  4平移动画
    //翻转
    if(isFrist){
        fristValue= 0f;
        secondValue=25f;
    }else{
        fristValue= 0f;
        secondValue=25f;
    }
    ObjectAnimator rotationX = ObjectAnimator.ofFloat(frist, "rotationX", fristValue, secondValue);
    rotationX.setDuration(300);
    //透明度动画
    if(isFrist){
        fristValue= 1f;
        secondValue=0.5f;
    }else{
        fristValue= 0.5f;
        secondValue=1f;
    }
    ObjectAnimator alpha = ObjectAnimator.ofFloat(frist, "alpha", fristValue, secondValue);
    alpha.setDuration(200);
    //缩放动画
    if(isFrist){
        fristValue= 1f;
        secondValue=0.8f;
    }else{
        fristValue= 0.8f;
        secondValue=1f;
    }
    ObjectAnimator scaleX = ObjectAnimator.ofFloat(frist, "scaleX", fristValue, secondValue);
    scaleX.setDuration(300);
    ObjectAnimator scaleY = ObjectAnimator.ofFloat(frist, "scaleY", fristValue, secondValue);
    scaleY.setDuration(300);
    //改正向旋转设置监听,执行完毕后再执行反向旋转
    if(isFrist){
        fristValue= 25f;
        secondValue=0f;
    }else{
        fristValue= 25f;
        secondValue=0f;
    }
    ObjectAnimator rotationX1 = ObjectAnimator.ofFloat(frist, "rotationX", fristValue, secondValue);
    rotationX1.setDuration(200);
    //延时执行动画
    rotationX1.setStartDelay(200);
    if(isFrist){
        fristValue= 0f;
        secondValue=-0.1f * frist.getHeight();
    }else{
        fristValue= -0.1f * frist.getHeight();
        secondValue=0f;
    }
    //由于缩放造成了离顶部有一段距离,需要平移上去
    ObjectAnimator translationY = ObjectAnimator.ofFloat(frist, "translationY", fristValue, secondValue);

    translationY.setDuration(200);
    //第二个view执行平移动画---往上平移
    if(isFrist){
        fristValue= second.getHeight();
        secondValue=0f;
    }else{
        fristValue= 0f;
        secondValue=second.getHeight();
    }
    ObjectAnimator translationY1 = ObjectAnimator.ofFloat(second, "translationY", fristValue, secondValue);
    translationY1.setDuration(200);
    translationY1.addListener(new AnimatorListenerAdapter() {
        @Override
        public void onAnimationStart(Animator animation) {
            super.onAnimationStart(animation);
            //动画开始的时候会回调
            second.setVisibility(View.VISIBLE);
            if(isFrist){
                bt.setClickable(false);
            }
        }
        @Override
        public void onAnimationEnd(Animator animation) {
            super.onAnimationEnd(animation);
            //动画结束的时候会回调
            if(!isFrist){
                bt.setClickable(true);
            }
        }
    });
    //将动画放到动画集合中
    AnimatorSet set=new AnimatorSet();
    set.playTogether(rotationX,alpha,scaleX,scaleY,rotationX1,translationY,translationY1);
    //开启动画
    set.start();
}

在对应的点击事件那里调用就可以了;

public void startFirstAnimation(View view){
//产品详情处点击事件
    setAnimator(true);
}
public void startSecondAnimation(View view){
    setAnimator(false);
}