Android动画

Android动画_第1张图片

Android 动画大致可以分为view animation(视图动画,补间动画) ,drawable animation(帧动画),property animation(属性动画)

View Animation

视图动画只能作用于view对象,是对view的变换,有以下的四种变换

  1. AlphaAnimation(透明度变化)
  2. ScaleAnimation(缩放变化)
  3. TranslateAnimation(位移变化)
  4. RotateAnimation (旋转变化)

还有一个AnimationSet让上面的动画集合起来一起运行,都是Animation的子类

Android动画_第2张图片

AlphaAnimation

直接alpha作为根元素




或者用set作为根元素



    

将xml加载到view中

alphaImageView.startAnimation(AnimationUtils.loadAnimation(MainActivity.this,R.anim.alpha));

再或者可以直接用java new 一个AlphaAnimation出来

AlphaAnimation alphaAnimation = new AlphaAnimation(0.0f, 1.0f);
alphaAnimation.setDuration(1000);//必须设置一个大于0的数值,默认是0
alphaImageView.startAnimation(alphaAnimation);

运行的gif就不放了,用到的属性说明下,

  • toAlpha 动画结束时的透明度 float (0.0 ~ 1.0,完全透明~完全不透明)
  • fromAlpha 动画开始的透明度 float
  • duration 动画持续时间 单位毫秒
  • fillAfter 动画结束后是否保持结束后的状态 boolean true为保持

ScaleAnimation

Android动画_第3张图片

参数介绍 :

  • fromX 动画开始时X轴的缩放比例,1.0表示当前view的正常比例
  • toX 动画结束时x轴的缩放比例,那么在x轴缩放的比例就是 toX - fromX
  • fromY 类似
  • toY 类似
  • pivotX x方向上的缩放起点,默认是0
  • pivotY Y方向上的缩放起点,默认是0
  • pivotType 缩放起点的类型,有三种
    /**
     * The specified dimension is an absolute number of pixels.
     * 默认是这种,相对于控件的0坐标
     */
    public static final int ABSOLUTE = 0;

    /**
     * The specified dimension holds a float and should be multiplied by the
     * height or width of the object being animated.
     * 相对与自身的宽/高的百分比,1.0 == 100%
     */
    public static final int RELATIVE_TO_SELF = 1;

    /**
     * The specified dimension holds a float and should be multiplied by the
     * height or width of the parent of the object being animated.
     * 相对于父控件的百分比
     */
    public static final int RELATIVE_TO_PARENT = 2;

demo

    ScaleAnimation scaleAnimation = new ScaleAnimation(1.0f, 1.5f, 1.0f, 1.5f);
    scaleAnimation.setDuration(2000);
    scaleAnimation.setFillAfter(true);
    alphaImageView.startAnimation(scaleAnimation);

Android动画_第4张图片

Android动画_第5张图片

把构造方法加上pivot,

    ScaleAnimation scaleAnimation = new ScaleAnimation(1.0f, 1.5f, 1.0f, 1.5f, 175f, 175f);
Android动画_第6张图片

我们把缩放起点设置为175,那么它的缩放就从这个起点向两边开始缩放

    ScaleAnimation scaleAnimation = new ScaleAnimation(1.0f, 1.5f, 1.0f, 1.5f,Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);   

Android动画_第7张图片

我们把它的起点模式改为relative_to_self,pivotX 和 pivotY改为0.5,意思就是它的缩放起点变为这个view的宽高的中点,向两边放大至原来的1.5倍

像上图实现图片点击放大,可以看到中间的红色框框,那就是imageView,其实它的真实位置并没有移动,这就是view animation,并不会真正改变view的位置,也不能。
对应的xml代码略...

TranslateAnimation

位移动画

Android动画_第8张图片

* @param fromXType Specifies how fromXValue should be interpreted. One of
 * Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
 * Animation.RELATIVE_TO_PARENT.

fromXType 就是用于解释解释fromCValue,其余的也是同样意思,和上面的ScaleAnimation

TranslateAnimation translateAnimation = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0.5f,Animation.RELATIVE_TO_SELF, 1.0f, 
Animation.ABSOLUTE,0, Animation.ABSOLUTE, 0);

translateAnimation.setDuration(2000);
translateAnimation.setFillAfter(true);
alphaImageView.startAnimation(translateAnimation);

不放图了.....

RotateAnimation

RotateAnimation rotateAnimation = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f,
                    Animation.RELATIVE_TO_SELF, 0.5f);
rotateAnimation.setDuration(2000);
rotateAnimation.setFillAfter(true);
alphaImageView.startAnimation(rotateAnimation);  

围绕图片中心转一圈,

AnimationSet




    
    
    

    

这里说一下50% 和 -50%p ,单纯只是%就是基于view本身,也就Animation.RELATIVE_TO_SELF,而%p就是基于view的parent,也就是Animation.RELATIVE_TO_PARENT.


Android动画_第9张图片

图中的view宽度为60px,父view为100px,左右两边平分,各为20px,针对view的动画


这个的意思就是:

view动画的开始位置是:view在图中的位置向左移动距离(0.5 * 100 = 50 ,为什么是左,-50%p)px,就是view在图片当前的位置向左移动50px就开始动画,这个移动的过程当然是看不到的,并且这不是view真正的移动,这里只是文字表述,view其实一直不改变它所在的位置。

结束位置就是view当前所在的位置,也就是view的左边距离父的左边20px

Interpolator

通过定义Interpolator可以改变动画的速率,比如加速,减速,匀速等,Android定义了一系列的interpolator

Android动画_第10张图片


accelerate decelerate interpolator

动画开始和动画结束的时候速度较慢,中间的速度较快。默认的插值器就是这个,在xml中的引用

android:interpolator="@android:anim/accelerate_decelerate_interpolator"

accelerate interpolator

动画从开始到结束的过程中一直加速,有个参数factor,就是设置速率的变化的,factor默认是1.0,factor的值越大 ,开始的速度就会变得更加慢,结束的速度更加快。


第一张图片是默认的factor=1.0,第二张是factor=10.0




第二张的开始速度明显慢于第二张,结束速度就貌似也是挺快

anticipate interpolator

动画开始的时候先向后方抛,然后再猛地向前掷,看gif


第二张图是默认的accelerate_decelerate_interpolator,第二张是anticipate_interpolator
anticipate_interpolator 有个参数控制着抛得力度mTension,默认是2.0,力度越大,向后抛得越远

第一张是默认2.0,第二张是10,

anticipate overshoot interplator

开始的时候跟anticipate interpolator是一样的,只是结束的时候,会超过预定的位置之后然后再回到预定的位置


也是包含一个参数tension,拉力的力度

第一张默认的2.0,第二张自定义tension是10,tension影响着开始和结束的拉力

bounce interpolator

动画在结束的时候会跳动

cycle interpolator

动画做圆周运动,最终会回到初始的地方,





    
    
    

    
    
    
    
    
    
    

    
    
    
    


    


图片会做一个圆周运动,这个类中有一个参数mCycles控制这个周期运动的次数

decelerate interpolator

动画一开始的速度非常快,然后一直减速,有个控制参数factor,跟accelerate中的一样,是加速度,gif就不放了

linear interpolator####

动画匀速运动,没有设置的参数

overshoot interpolator

跟anticipate overshoot interpolator 差不多,就是没有开始的向后抛

https://github.com/lijinxiong/Animation


drawable animation

帧动画,也叫做视图动画,动画组成就是靠一张张的图片,快速的播放,达到动画的效果

xml




    
    
    
    
    


java

ImageView mImageView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mImageView = (ImageView) this.findViewById(R.id.my_image_view);

    AnimationDrawable animationDrawable = (AnimationDrawable) mImageView.getBackground();
    mImageView.setOnClickListener(new OnClilckListener(){   
        animationDrawable.start();  
    });

Java

    mImageView = (ImageView) this.findViewById(R.id.my_image_view);

    AnimationDrawable animationDrawable = new AnimationDrawable();

    animationDrawable.addFrame(getResources().getDrawable(R.drawable._01), 100);
    animationDrawable.addFrame(getResources().getDrawable(R.drawable._02), 100);
    animationDrawable.addFrame(getResources().getDrawable(R.drawable._03), 100);
    animationDrawable.addFrame(getResources().getDrawable(R.drawable._04), 100);
    animationDrawable.addFrame(getResources().getDrawable(R.drawable._05), 100);
    animationDrawable.setOneShot(false);
    
    mImageView.setBackground(animationDrawable);
    
    mImageView.setOnClickListener(new OnClilckListener(){   
        animationDrawable.start();  
    });

注意事项:

/**
 * Starts the animation from the first frame, looping if necessary. This         method has no effect
 * if the animation is running.
 * 

* Note: Do not call this in the * {@link android.app.Activity#onCreate} method of your activity, because * the {@link AnimationDrawable} is not yet fully attached to the window. * If you want to play the animation immediately without requiring * interaction, then you might want to call it from the * {@link android.app.Activity#onWindowFocusChanged} method in your * activity, which will get called when Android brings your window into * focus. * * @see #isRunning() * @see #stop() */

就是说我们不能再activity的onCreate方法中调用start方法,因为这个时候的AnimationDrawable并没有完全的依附到了window上面去,如果你不需要用户交互的去触发这个动画,可以在onWindowFocusChanged中调用start方法
https://github.com/lijinxiong/FrameAnimation

Property Animation

Property Animation是Android3.0的时候引进的,可以对任意的对象的属性进行动画变换。你设定一个开始值和一个结束值,然后设定从开始值到结束值之间值是怎么变化的,还有整个变化所需要的时间,然后就通过不断的setProperty(),来达到动画的效果

与view animation的差别:先说文件的位置,xml文件,view animation是在anim 目录下的,而property animation是在animator。view animation并没有改变view 的真正位置,而property animation是真正改变view的属性来达到动画效果,当然是真正改变view的位置的。

先介绍一些用到的某些类和变量

  • duration 动画时间
  • 动画的执行类
  • TimeInterpolator 时间插值器
    Android动画_第11张图片
  • fraction 一个0-1的分数,由Animator 根据 当前动画播放时间/duration ,再经过xxxInterpolator计算,不同的interpolator结果不一样
  • TypeEvaluator 根据fraction的值计算出动画改变属性的属性值

ValueAnimator

ValueAnimator valueAnimator = new ValueAnimator();
    valueAnimator.setDuration(2000);//设置动画时间,默认是300
    valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());//设置插值器,默认也是这个
    valueAnimator.setFloatValues(0, 200);//设置开始值和结束值


    //监听属性值的改变 
    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            float tem = (float) animation.getAnimatedValue();
            Log.d(TAG, "onAnimationUpdate: " + tem);
            view.setTranslationY(tem);

        }
    });
    //开始动画
    valueAnimator.start();
04-25 20:37:43.635 2224-2224/com.demo.propertyanimation D/MainActivity: onAnimationUpdate: 192.38795
04-25 20:37:43.651 2224-2224/com.demo.propertyanimation D/MainActivity: onAnimationUpdate: 193.37679
04-25 20:37:43.668 2224-2224/com.demo.propertyanimation D/MainActivity: onAnimationUpdate: 194.24664
04-25 20:37:43.684 2224-2224/com.demo.propertyanimation D/MainActivity: onAnimationUpdate: 195.10565
04-25 20:37:43.701 2224-2224/com.demo.propertyanimation D/MainActivity: onAnimationUpdate: 195.89684
04-25 20:37:43.719 2224-2224/com.demo.propertyanimation D/MainActivity: onAnimationUpdate: 196.57901
04-25 20:37:43.734 2224-2224/com.demo.propertyanimation D/MainActivity: onAnimationUpdate: 197.23698
04-25 20:37:43.751 2224-2224/com.demo.propertyanimation D/MainActivity: onAnimationUpdate: 197.82564
04-25 20:37:43.768 2224-2224/com.demo.propertyanimation D/MainActivity: onAnimationUpdate: 198.31593
04-25 20:37:43.784 2224-2224/com.demo.propertyanimation D/MainActivity: onAnimationUpdate: 198.76883

那么这个属性值是怎么计算出来的

  1. ValueAnimation先根据当前已经播放的动画时间/我们设置的duration时间,得到fraction
  2. 将这个值传递给动画设置的interpolator,这里对应的是AccelerateDecelerateInterpolator,它再根据本身的意义设置fraction,假如这里是LinearInterpolator,那么这个fraction 将不变
  3. 将fraction传递给TypeEvaluate,这里是FloatEvaluate,根据fraction计算出当前的属性值
    FloatEvaluate
public class FloatEvaluator implements TypeEvaluator {
public Float evaluate(float fraction, Number startValue, Number endValue) {
    float startFloat = startValue.floatValue();
    return startFloat + fraction * (endValue.floatValue() - startFloat);
}
}

ObjectAnimator

作为ValueAnimator的子类,ObjectAnimator不同的是,它需要设定动画作用的目标,也就是说这个动画应用在哪个目标上

ObjectAnimator animator = ObjectAnimator.ofFloat(view, "y", 0, 200);

    animator.setDuration(2000);
    animator.setInterpolator(new OvershootInterpolator());

    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {

            float tem = (float) animation.getAnimatedValue();
            Log.d(TAG, "onAnimationUpdate: " + tem);
        }
    });

    animator.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) {

        }
    });
    animator.start();
}
  • ofFloat(Object target, String propertyName, float... values)
    静态方法,返回一个ObjectAnimator,ValueAnimator也有这些静态方法
    Android动画_第12张图片

    第一个参数就是动画应用在哪个对象,第二个参数就是设置这个动画改变的属性,第三个可变参数,写一个就是属性的开始值,两个就是一个开始值一个结束值。这里改变的属性值必须有setXxx方法,因为是通过反射调用设置这个属性的,还有就是这这个方法中必须包含对这个view 的重绘的方法,view.postInvalidate(); / view.invalidate();否则你设置了这个属性也不能在界面上马上看到效果,也就没有动画可言。
  • addUpdateListener 每次对应的TypeEvaluate计算完属性值都会回调这个方法
  • addListener 动画的开始结束取消重复监听,可以使用AnimatorListenerAdapter代替,自己选择监听哪个

TypeEvaluate

Android动画_第13张图片

自定义TypeEvaluate

实现抛物线,x方向是100px/s,y方向的加速度是200px/s*s

 ValueAnimator animator = ValueAnimator.ofObject(new TypeEvaluator() {
        @Override
        public PointF evaluate(float fraction, PointF startValue, PointF endValue) {

            PointF pointF = new PointF();
            //fuction = t /duration
            pointF.x = 100 * 2 * fraction;
            pointF.y = 0.5f * 200 * 2 * fraction * 2 * fraction;

            return pointF;
        }
    }, new PointF(0, 0));

    animator.setDuration(2000);

    animator.setInterpolator(new LinearInterpolator());
    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            PointF p = (PointF) animation.getAnimatedValue();

            view.setTranslationX(p.x);
            view.setTranslationY(p.y);
        }
    });
    animator.start();

xml实现

objectAnimator






    Animator animator = AnimatorInflater.loadAnimator(this, R.animator.value_animator);
    animator.setTarget(view);
    animator.start();

animatorSet



    

    
    
    


java

AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.value_animator_set);
set.setTarget(view);

set.start();

set中的一个参数就是ordering,顺序可以选择together(同一时间所有动画一起开始),也可以选择sequentially(按set中的顺序顺序一个个开始)。
纯java animatorSet

AnimatorSet set= new AnimatorSet();

    set.play(AnimatorInflater.loadAnimator(this, R.animator.value_animator)).
            with(new ObjectAnimator().setDuration(2000).ofFloat(view, "x", 0, 200));


    set.setTarget(view);
    set.setDuration(2000);

    set.start();

https://github.com/lijinxiong/note/blob/master/Android/%E5%8A%A8%E7%94%BB.md

你可能感兴趣的:(Android动画)