UI别人家的Android开发经验动画相关

吐血总结【Android动画学习-你必须要知道的动画知识点】

2017-12-18  本文已影响63人  芒果味的你呀

Animations

动画系统:Developer-Animation
Android框架提供了两个动画系统:属性动画和视图动画。两个动画系统都是可行的选择,但是总的来说,属性动画系统是首选的方法,因为它更灵活,提供了更多的特性。
android3.0之后 动画分类如图: image.png

接下来我们具体讲解这三种动画:


一、视图动画:【ViewAnimation】

1. 帧动画(FrameAnimation):它允许您加载可绘制的资源,并将它们显示为一个接一个的帧。一帧一帧的动画,加载一系列Drawable资源来创建动画,这种传统动画某种程度上就是创建不同图片序列,顺序播放,就像电影胶片、幻灯片一样。(这种确实很简单,直接使用UI切好的图就行,但是图片过多,也十分容易内存溢出oom,所以一般不建议使用)

2. 补间动画(TweenAnimation) :AlphaAnimation(xml中alpha标签), RotateAnimation(xml中rotate标签), ScaleAnimation(xml中scale标签), TranslateAnimation(xml中translate标签),分别对应透明度、旋转、缩放、位移四种变化。

使用方式一:xml定制动画(文件处于res/anim/地址下)

<?xml version="1.0" encoding="utf-8"?> 
<set xmlns:android="http://schemas.android.com/apk/res/android"> 
<alpha 
    android:fromAlpha="0.0"  
    android:toAlpha="1.0"  
    android:duration="500"  /> 
</set> 
<!--  
    fromAlpha:开始时透明度 
    toAlpha: 结束时透明度 
    duration:动画持续时间 -->
<set xmlns:android="http://schemas.android.com/apk/res/android">
<rotate                                         
      android:interpolator="@android:anim/accelerate_decelerate_interpolator" 
    android:fromDegrees="300" 
    android:toDegrees="-360" 
    android:pivotX="10%" 
    android:pivotY="100%" 
    android:duration="10000" /> 
</set> 
<!--  
  fromDegrees   动画开始时的角度 
  toDegrees     动画结束时物件的旋转角度,正代表顺时针   
  pivotX    属性为动画相对于物件的X坐标的开始位置
----旋转中心的x坐标,浮点数或是百分比。浮点数表示相对于Object的左边缘,如5; 百分比表示相对于Object的左边缘,如5%; 另一种百分比表示相对于父容器的左边缘,如5%p; 一般设置为50%表示在Object中心
  pivotY    属性为动画相对于物件的Y坐标的开始位置 
--- 旋转中心的Y坐标,浮点数或是百分比。浮点数表示相对于Object的上边缘,如5; 百分比表示相对于Object的上边缘,如5%; 另一种百分比表示相对于父容器的上边缘,如5%p; 一般设置为50%表示在Object中心
duration  持续时间,表示从android:fromDegrees转动到android:toDegrees所花费的时间,单位为毫秒。1000ms=1s 可以用来计算速度。
interpolator表示变化率,但不是运行速度。一个插补属性,可以将动画效果设置为加速,减速,匀速,反复,反弹等。默认为开始和结束慢中间快.
其他:
android:repeatCount 重复的次数,默认为0,必须是int,可以为-1表示不停止
android:repeatMode 重复的模式,默认为restart,即重头开始重新运行,可以为reverse即从结束开始向前重新运行。在android:repeatCount大于0或为infinite时生效
android:detachWallpaper 表示是否在壁纸上运行
android:startOffset 在调用start函数之后等待开始运行的时间,单位为毫秒,若为10,表示10ms后开始运行
android:zAdjustment 表示被animated的内容在运行时在z轴上的位置,默认为normal。
normal保持内容当前的z轴顺序
top运行时在最顶层显示
bottom运行时在最底层显示
   -->
<?xml version="1.0" encoding="utf-8"?> 
<set xmlns:android="http://schemas.android.com/apk/res/android"> 
<scale   
    android:interpolator= "@android:anim/decelerate_interpolator"       
    android:fromXScale="0.0"   
    android:toXScale="1.5"   
    android:fromYScale="0.0"   
    android:toYScale="1.5"   
    android:pivotX="50%"   
    android:pivotY="50%"   
    android:startOffset="0"   
    android:duration="10000"  
    android:repeatCount="1"   
    android:repeatMode="reverse"  /> 
</set> 
 
<!--  
fromXDelta,fromYDelta       起始时X,Y座标,屏幕右下角的座标是X:320,Y:480 
toXDelta, toYDelta      动画结束时X,Y的座标 --> <!--  
interpolator                    指定动画插入器
常见的有加速减速插入器         accelerate_decelerate_interpolator
加速插入器               accelerate_interpolator,
减速插入器               decelerate_interpolator。 
fromXScale,fromYScale,         动画开始前X,Y的缩放,0.0为不显示,  1.0为正常大小
toXScale,toYScale,          动画最终缩放的倍数, 1.0为正常大小,大于1.0放大
pivotX,  pivotY         动画起始位置,相对于屏幕的百分比,两个都为50%表示动画从屏幕中间开始 
startOffset,                动画多次执行的间隔时间,如果只执行一次,执行前会暂停这段时间,
                    单位毫秒 duration,一次动画效果消耗的时间,单位毫秒,
                    值越小动画速度越快 repeatCount,动画重复的计数,动画将会执行该值+1次 
                    repeatMode,动画重复的模式,reverse为反向,当第偶次执行时,动画方向会相反。
                    restart为重新执行,方向不变 -->
<?xml version="1.0" encoding="utf-8"?> 
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate 
    android:fromXDelta="320" 
    android:toXDelta="0" 
    android:fromYDelta="480" 
    android:toYDelta="0" 
    android:duration="10000" /> 
</set> 
<!--  
fromXDelta,fromYDelta   起始时X,Y座标,屏幕右下角的座标是X:320,Y:480 
toXDelta, toYDelta     动画结束时X,Y的座标 -->

加载xml动画:

//xml动画文件
ImageView imageBg = (ImageView) content.findViewById(R.id.imageView);
Animation animation = AnimationUtils.loadAnimation(context, R.anim.splash_scale);
animation.setInterpolator(new LinearInterpolator());
imageBg.startAnimation(animation);

使用方式二、java代码方式实现定制并加载动画

xml里有的动画属性都可以通过java代码创建。根据需要定制自己的动画

//平移动画 四个参数fromX,toX,fromY,toY。而这个X,Y都是相对于当前这个控件的位置来说的。
//就是从当前控件的(X+fromX,Y+fromY)移动到(X+toX,Y+toY),
//(其中这个X和Y是最刚开始这个控件的X和Y坐标。就是动画都还没开始的时候的坐标。)
ImageView imageBg = (ImageView) content.findViewById(R.id.imageView);
TranslateAnimation anim = new TranslateAnimation(0,100,0,100);
anim.setDuration(5000);
anim.setInterpolator(new LinearInterpolator());
anim.setFillAfter(true);
imageBg .startAnimation(anim);

AnimationListener和AnimationSet

通过AnimationListener可以监听Animation的运行过程,有三个方法分别是Animation开始的时候调用,完成的时候调用,重复的时候调用。
AnimationSet,动画集合。 我们最常用的是调用其 addAnimation 将一个个不一样的动画组织到一起来,然后调用view 的 startAnimation 方法触发这些动画执行。

            AnimationSet as=new AnimationSet(true);  
            RotateAnimation al=new RotateAnimation(0,-720,Animation.RELATIVE_TO_PARENT,0.5f,Animation.RELATIVE_TO_PARENT,0.5f);  
            al.setDuration(3000);  
            al.setAnimationListener(new AnimationListener(){  
  
                public void onAnimationStart(Animation animation) {  
                    // TODO Auto-generated method stub  
                      
                }  
  
                public void onAnimationEnd(Animation animation) {  
                    // TODO Auto-generated method stub  
                      
                }  
  
                public void onAnimationRepeat(Animation animation) {  
                    // TODO Auto-generated method stub  
                      
                }  
                  
            });  
            as.addAnimation(al);  
            iv.startAnimation(as);  

setAnimation和startAnimation区别

setAnimation是告诉该控件我待会要执行什么动画,而要执行的的动画,是需要手动添加的。并且需要父view在动画快要开启的时候,调用invalidate。需要一定的条件限制。
而startAnimation告诉该控件,我要立马执行该动画,该动画就是已经设置好的动画。调用它时就会立即开始动画。


属性动画 【PropertyAnimation】

对比

ViewAnimation本身是通过改变View的绘制方式来实现动画的,View对象本身的属性值并没有改变,对象仍然停留在原始位置.
Property Animation系统可以通过修改 View 对象实际的属性值(属性会有相应的 getter、setter )来实现屏幕上的动画效果。此外,当属性值发生变化时,Views 也会自动调用 invalidate() 方法来刷新屏幕。

View Animation相当简单,不过只能支持简单的缩放、平移、旋转、透明度基本的动画和帧动画,且有一定的局限性。比如:

  • 你希望View有一个颜色的切换动画;
  • 你希望可以使用3D旋转动画;
  • 你希望当动画停止时,View的位置就是当前的位置;
  • 修改组件的背景颜色
    这些View Animation都无法做到。
    这也就是Property Animation产生的原因。
    PropertyAnimation就是通过动画的方式改变对象的属性。
    接下来我们详细讲解PropertyAnimation。
1.PropertyAnimation-沿一定时间顺序,通过改变View的属性,从而得到动画效果。使得“眼见为实”,动画之后,Object对象的属性值被实实在在的改变了。Property animation能够通过改变View对象的实际属性来实现View动画,任何时候View属性的改变,View能自动调用invalidate()来实时刷新。
2.总的来说,属性动画就是,动画的执行类来设置动画操作的对象的属性(持续时间,开始和结束的属性值,时间差值等),然后系统会根据设置的参数动态的变化对象的属性。

接下来讲解属性动画在实践中的使用:

【关于Interpolator、TypeEvaluator】

参看这篇文章:Android动画之Interpolator插补器和TypeEvaluator估值器

【关于Animator监听器 】

Property Animation提供了Animator.AnimatorListener和Animator.AnimatorUpdateListener两个监听器用于动画在播放过程中的重要动画事件。下面是两个监听器接口和方法的一些介绍和说明:

       animator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
            }
        });
        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) {

            }
        });

【关于AnimatorInflater】

上面讲到ViewAnimation有许多xml加载,当然PropertyAnimation也可以对应xml加载,位置为res/animator/
animator.xml

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2000"
android:propertyName="alpha"
android:valueFrom="0.1"
android:valueTo="1.0"
android:valueType="floatType" />

调用就用到了AnimatorInflater类了

 Animator animator = AnimatorInflater.loadAnimator(getApplicationContext(), R.animator.animator);
animator.setTarget(imageView);
animator.start();

组合动画也可以xml加载

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:ordering="together">
orderring属性设置为together,还有另一个值:sequentially(表示一个接一个执行)。
    <objectAnimator
        android:duration="1000"
        android:propertyName="scaleX"
        android:valueFrom="1"
        android:valueTo="0.5" />
    <objectAnimator
        android:duration="1000"
        android:propertyName="scaleY"
        android:valueFrom="1"
        android:valueTo="0.5" />
</set>

【关于动画属性值】

在 Android 3.0 中给 View 增加了一些新的属性以及相应的 getter、setter 方法。Property Animation系统可以通过修改 View 对象实际的属性值来实现屏幕上的动画效果。此外,当属性值发生变化时,Views 也会自动调用 invalidate() 方法来刷新屏幕。 View 类中新增的便于实现 property 动画的属性包括:

上述我们提到的属性也就是接下来ObjectAnimator使用中的第二个参数,操作对象的属性值。

当然我们也可以自定义view的动画属性,但必须带有一个 setter 方法(以骆驼拼写法命名),格式类似 set<propertyName>()。 因为 ObjectAnimator 会在动画期间自动更新属性值,它必须能够用此 setter 方法访问到该属性。getter不是必须,而什么时候必须需要getter方法呢?如果在调用 ObjectAnimator 的某个工厂方法时,我们只为 values... 参数指定了一个值,那此值将被认定为动画属性的结束值。 这样的话,动画显示的属性必须带有一个 getter 方法,用于获取动画的起始值。 此 getter 方法必须以get<propertyName>()的格式命名。

【使用ObjectAnimator实现动画】

1.通过调用ofFloat()、ofInt()等方法创建ObjectAnimator对象,并设置目标对象、需要改变的目标属性名、初始值和结束值;
2.设置动画的持续时间、是否重复及重复次数等属性;
3.启动动画。

ObjectAnimator objectAnimator1 = ObjectAnimator.ofFloat(imageView, "translationX", 300);
objectAnimator1.setInterpolator(new AccelerateInterpolator());
objectAnimator1.setDuration(2000);
objectAnimator.setRepeatCount(ValueAnimator.INFINITE);//Animation.INFINITE 表示重复多次
objectAnimator.setRepeatMode(ValueAnimator.RESTART);//RESTART表示从头开始,REVERSE表示从末尾倒播
objectAnimator1.start();

1 . 第一个参数:设置目标对象,即操纵的view
2 . 第二个参数:设置操作的动画的属性值(见上面讲解的动画属性值)
3 . 第三个参数:可变数组参数 (初始值,中间值,结束值)。可以有一个到N个,如果是一个值的话默认这个值是动画过渡值的结束值。如果有N个值,动画就在这N个值之间过渡。

【使用ValueAnimator实现动画】

那一般使用ValueAnimator实现动画分为以下七个步骤:
1. 调用ValueAnimation类中的ofInt(int...values)、ofFloat(String propertyName,float...values)等静态方法实例化ValueAnimator对象,并设置目标属性的属性名、初始值或结束值等值;
2.调用addUpdateListener(AnimatorUpdateListener mListener)方法为ValueAnimator对象设置属性变化的监听器;
3.创建自定义的Interpolator,调用setInterpolator(TimeInterpolator value)为ValueAniamtor设置自定义的Interpolator;(可选,不设置默认为缺省值)
4.创建自定义的TypeEvaluator,调用setEvaluator(TypeEvaluator value)为ValueAnimator设置自定义的TypeEvaluator;(可选,不设置默认为缺省值)
5.在AnimatorUpdateListener 中的实现方法为目标对象的属性设置计算好的属性值。
6.设置动画的持续时间、是否重复及重复次数等属性;
7.为ValueAnimator设置目标对象并开始执行动画。

【ObjectAnimator和ValueAnimator的对比】

【PropertyValuesHolder】

针对同一个对象多个属性,同时作用多种动画

PropertyValuesHolder propertyValuesHolder1 = PropertyValuesHolder.ofFloat("translationX", 300f);
PropertyValuesHolder propertyValuesHolder2 = PropertyValuesHolder.ofFloat("alpha", 1f, 0.5f);
PropertyValuesHolder propertyValuesHolder3 = PropertyValuesHolder.ofFloat("scaleX", 1f, 0, 1f);
PropertyValuesHolder propertyValuesHolder4 = PropertyValuesHolder.ofFloat("scaleY", 1f, 0, 1f);
ObjectAnimator.ofPropertyValuesHolder(imageView, propertyValuesHolder1, propertyValuesHolder2, propertyValuesHolder3, propertyValuesHolder4)
        .setDuration(5000).start();

【关于AnimatorSet动画集合】

可以调用其playTogether(同时执行)、playSequentially(顺序执行)、play、before、with、after 等方法设置动画的执行顺序,然后调用其start 触发动画执行。

ObjectAnimator objectAnimator1 = ObjectAnimator.ofFloat(imageView, "alpha", 1f, 0.5f);
ObjectAnimator objectAnimator2 = ObjectAnimator.ofFloat(imageView, "translationY", 300);
ObjectAnimator objectAnimator3 = ObjectAnimator.ofFloat(imageView, "scaleX", 1f, 0, 1f);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.setDuration(5000);
animatorSet.playTogether(objectAnimator1, objectAnimator2,objectAnimator3);
animatorSet.start();
AnimatorSet 和 AnimationSet 区别

AnimationSet 与 AnimatorSet 最大的不同在于:
AnimationSet 使用的是 Animation 子类、AnimatorSet 使用的是 Animator 的子类。
-----Animation 是针对视图外观的动画实现,动画被应用时外观改变但视图的触发点不会发生变化,还是在原来定义的位置。 (也就是作用于视图动画)
-----Animator 是针对视图属性的动画实现,动画被应用时对象属性产生变化,最终导致视图外观变化。(也就是作用于属性动画)

AnimatorSet 和 PropertyValuesHolder 区别

--- AnimatorSet可以将作用于多个view多个属性的动画集合起来,而PropertyValuesHolder针对同一个对象多个属性。
--- AnimatorSet多了playTogether(同时执行)、playSequentially(顺序执行)、play(objectAnimator1).with(objectAnimator2)、before、after这些方法协同工作。

【关于View的animate方法】

Android 3.0后,谷歌给View增加animate方法直接驱动属性动画。

可以直接这样写就完成了imageview 的透明度有1-0.5以及位置移动到300动画:
imageView.animate()
.alpha(0.5f)
.y(300)
.setDuration(2000);

此后在SDK12,SDK16又分别添加了withStartAction和withEndAction用于在动画前,和动画后执行一些操作。
当然也可以.setListener(listener)等操作
                imageView.animate()//
                .alpha(0)//  由1到0
                .y(mScreenHeight / 2)
                .setDuration(1000)  
                // need API 12  
                .withStartAction(new Runnable()  
                {  
                    @Override  
                    public void run()  
                    {  
                    }  
                    // need API 16  
                }).withEndAction(new Runnable()  
                {  
  
                    @Override  
                    public void run()  
                    {  
              
                        runOnUiThread(new Runnable()  
                        {  
                            @Override  
                            public void run()  
                            {  
                                imageView.setY(0);  
                                imageView.setAlpha(1.0f);  
                            }  
                        });  
                    }  
                }).start();  
其实上面的这段操作通过PropertyValuesHolder也可以实现:
PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("alpha", 1f,  
            0f, 1f);  
PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 0,  
            mScreenHeight / 2, 0);  
ObjectAnimator.ofPropertyValuesHolder(imageView, pvhX, pvhY).setDuration(1000).start();  

【布局动画】

Android动画学习之为ViewGroup中的Layout设置动画实例

之后会总结出一篇动画实践的文章,汇总一些好看的常用的动画。

最后的最后不要吝啬你的小心心❤️ 你们的鼓励是我最大的动力~

上一篇下一篇

猜你喜欢

热点阅读