Android 动画(Frame, View, Property)的区别,属性动画及动画框架Demo

Frame/View动画通过不断的调用OnDraw方法来进行UI的绘制,而Property属性动画一般只调用ViewGroup进行绘制。

-- ViewGroup的绘制
ViewGroup通常是不需要绘制的,因为本身就没有需要绘制的东西。
如果不是指定ViewGroup的背景色,那么ViewGroup的o'nDraw方法都不会被调用。
ViewGroup会使用dispatchDraw()方法绘制子View,其过程是遍历子View,调用子View的绘制方法进行绘制。

  缩放动画ScaleAnimation/移位动画TranslateAnimation/透明度动画AlphaAnimation/旋转动画RotateAnimation;
平移(Translate)、旋转(Rotate)、缩放(Scale)、不透明度(Alpha),AnimationSet.。

-- “为什么属性动画移动后仍可点击- https://mp.weixin.qq.com/s/hiWxzJkDjvDoClOUuJI7CA
  播放补间动画的时候,我们所看到的变化,都只是临时的。而属性动画呢,它所改变的东西,却会更新到这个View所对应的矩阵中,所以当ViewGroup分派事件的时候,会正确的将当前触摸坐标,转换成矩阵变化后的坐标,这就是为什么播放补间动画不会改变触摸区域的原因了。

自定义View动画过程主要是一个矩阵变换的过程。

-- 你所不知道的Activity转场动画——ActivityOptions
ActivityOptionsCompat是一个静态类,提供了为数不多的几个方法,下面我们来罗列一下:
1. ActivityOptionsCompat.makeCustomAnimation(Context context, int enterResId, int exitResId)

2. ActivityOptionsCompat.makeScaleUpAnimation(View source,int startX, int startY, int startWidth, int startHeight)

3. ActivityOptionsCompat.makeThumbnailScaleUpAnimation(View source,Bitmap thumbnail, int startX, int startY)

4. ActivityOptionsCompat.makeSceneTransitionAnimation(Activity activity, View sharedElement, String sharedElementName)

5. ActivityOptionsCompat.makeSceneTransitionAnimation(Activity activity,Pair<View, String>…  sharedElements)

> 动画(Frame, View, Property)的区别:

-- android动画分三类:一是View 动画,又叫Tween动画,二是frame 动画(帧动画),又叫drawable 动画,三是属性动画,即property animation. 
  (1)Frame Animation(帧动画)主要用于播放一帧帧准备好的图片,类似GIF图片,优点是使用简单方便、缺点是需要事先准备好每一帧图片;帧动画 对应AnimationDrawable类,继承自DrawableContainer,通过加载多个Drawable来一帧一帧播放达到动画效果。尽管很多人觉得这个不值一提,但是某些动画效果,如显示个小羊吃草还必须得用这个动画。 
  (2)Tween Animation(补间动画)仅需定义开始与结束的关键帧,而变化的中间帧由系统补上,优点是不用准备每一帧,缺点是只改变了对象绘制,而没有改变View本身属性。因此如果改变了按钮的位置,还是需要点击原来按钮所在位置才有效。

   补间动画是只能对View对象进行动画操作的。而属性动画就不再受这个限制,它可以对任意对象进行动画操作。动画中的调用了invalidate()方法,这样的话onDraw()方法就会重新调用。补间动画是只能实现移动、缩放、旋转和淡入淡出这四种动画操作的,想要实现对View的颜色进行动态改变,补间动画是没有办法做到的。

  View动,根据作用又分为缩放动画ScaleAnimation/移位动画TranslateAnimation / 透明度动画AlphaAnimation / 旋转动画RotateAnimation,这四个动画都继承android.view.animation下的Animation类。继承Animation的除了这四个类外,还有AnimationSet. View动画,包名android.view.animation,基类为Animation,核心子类为TranslateAnimation,ScaleAnimation,AlphaAnimation,RotateAnimation及AnimationSet。 
  (3)Property Animation(属性动画)是3.0后推出的动画,优点是使用简单、降低实现的复杂度、直接更改对象的属性、几乎可适用于任何对象而仅非View类,缺点是需要3.0以上的API支持,限制较大!但是目前国外有个开源库,可以提供低版本支持!

   属性动画,该动画从android3.0引入,API11引入,是为了弥补view动画的不足。正式项目里用的话为了兼容android2.3可以用NineOldAndroids,直接将生成的jar包放进去就ok了。
  Property动画,包名android.animation,基类为Animator,核心子类为AnimatorSet,ValueAnimator,ObjectAnimator,TimeAnimator.
  view 动画+updateParams 约等于property动画效果。但是切忌,使用view动画+updateParams策略时,务必注意不要使用transAnim.setFillAfter(true)
  如果想改变动画后view的属性,如位置,可以用属性动画也可以用view动画+updateParams,当然前者更省事。在有些情况下,仅仅是想得到动画的呈现,动画结束后的位置就是view的初始位置,如view从一个地方飞过来,动画结束时view的位置就是view的位置时,此时view动画最合适!

-- 三种动画:View动画、帧动画、属性动画:

1. View animation只能应用于View对象,而且只支持一部分属性,渐变动画只支持四种类型:平移(Translate)、旋转(Rotate)、缩放(Scale)、不透明度(Alpha)。
2. Frame动画,传统的动画方法,通过顺序的播放排列好的图片来实现,类似电影补间动画和帧动画。

3. 属性动画要求动画作用的对象提供该属性的get和set方法,属性动画根据你传递的该熟悉的初始值和最终值,以动画的效果多次去调用set方法,每次传递给set方法的值都不一样,确切来说是随着时间的推移,所传递的值越来越接近最终值。总结一下,你对object的属性xxx做动画,如果想让动画生效,要同时满足两个条件:

  a. object必须要提供setXxx方法,如果动画的时候没有传递初始值,那么还要提供getXxx方法,因为系统要去拿xxx属性的初始值(如果这条不满足,程序直接Crash)
  b. object的setXxx对属性xxx所做的改变必须能够通过某种方法反映出来,比如会带来ui的改变啥的(如果这条不满足,动画无效果但不会Crash)

-- 属性动画不仅兼容视图动画,还能解决许多视图动画无法解决的问题,可以看做更加广义的动画。属性动画框架在Android3.0中引入,是一个健壮的框架,它几乎可以把任何对象变成动画。属性动画的目标与宗旨是:能够根据时间的推移来实时改变任何对象的属性值,而不用关心该对象是否要绘制在屏幕上。属性动画框架主要包含几个部分:动画执行类、动画监听机类、计算估值器、动画插值器.

    ValueAnimator、ObjectAnimator、AnimatorSet。ValueAnimator是最常用的属性动画时间引擎,ValueAnimator本身不作用于任何对象,主要用于对一个值做动画,根据当前动画进度提供计算值,至于如何利用这个值,则完全不关心。ObjectAnimator:顾名思义,是面向对象的ValueAnimator,需要指定特定的操作对象及相应属性,这样Android系统便可以自动更新对象的属性。AnimatorSet是属性动画集合,主要用于整合多个动画,比如先后执行、并发执行等.

-- View动画和属性动画的区别:

  补间动画是只能实现移动、缩放、旋转和淡入淡出这四种动画操作的,功能限定死就是这些,基本上没有任何扩展性可言。比如我们想要实现对View的颜色进行动态改变,补间动画是没有办法做到的。但是属性动画就不会受这些条条框框的限制,它的扩展性非常强,对于动态改变View的颜色这种功能是完全可是胜任的.属性动画的高级用法中最有技术含量的也就是如何编写出一个合适的TypeEvaluator。

   补间动画是只能对View对象进行动画操作的。而属性动画就不再受这个限制,它可以对任意对象进行动画操作。比如说我们有一个自定义的View,在这个View当中有一个Point对象用于管理坐标,然后在onDraw()方法当中就是根据这个Point对象的坐标值来进行绘制的。也就是说,如果我们可以对Point对象进行动画操作,那么整个自定义View的动画效果就有了。

   在API3.0(Honeycomb), SDK新增了一个android.animation包,里面的类是实现动画效果相关的类,通过Honeycomb API,能够实现非常复杂的动画效果,但是如果开发者想在3.0以下使用这一套API, 则需要使用开源框架Nine Old Androids,在这个库中会根据我们运行的机器判断其SDK版本,如果是API3.0以上则使用Android自带的动画类,否则就使用Nine Old Androids库中,这是一个兼容库。

-- 属性动画总结
    属性动画与视图动画最大的区别是:属性动画能够实时改变Object的属性,而视图动画无法做到,并且属性动画应用的范围更广,限制更小。很多场合下,如果视图动画无法满足需求,不放考虑属性动画,然而功能的强大导致了实现的复杂度提升,所以如果视图动画足够满足需求,可以不用视图动画。

-- 属性动画动画的插值器(Interpolator)和估值器(TypeEvaluator),属性动画ObjectAnimator和ValueAnimator ,ViewPropertyAnimator(SDK 3.1系统当中附增),PropertyValuesHolder ,AnimatorSet
    1.属性动画是通过改变某个控件的属性值来创造动画,比如在规定的时间内改变某个控件的X坐标,则会产生一个平移的动画效果。
    2.坚持使用属性动画和帧动画,而不要使用补间动画,补间动画会造成控件移动到目的地但是控件的热点(产生事件的范围)仍然在原地
    3.属性动画几乎可以产生一切你想要的效果,一般在插入动画时,默认为匀速从起点到终点,可以通过插值改变从起点到终点的效果
    4.属性动画分为ObjectAnimator和ValueAnimator,其中ObjectAnimator是继承于ValueAnimator

-- 属性动画插值器原理:本质是时间的函数,定义了动画的变化规律(提前/延迟执行默认的时间点来达到加速/减速的效果!);
估值器的是用来决定属性的计算方式,最终使用反射机制来改变属性变化。

  TypeEvaluator(估值器)是直接改变动画的属性值的,比如要改变颜色属性,可以直接改变其值为"#FFFFFF",而Interpolator(插值器)改变的是进度,如可以直接指定瞬间完成动画整体的80%。但是两者不是孤立存在的,不是各自改变各自的东西。Interpolator负责调节动画进度变化快慢,TypeEvaluator负责改变动画最终的属性值,它们之间以Interpolator返回的当前进度值相联系。

-- 自定义TypeEvaluator(估值器)
 class OscillationEvaluator implements TypeEvaluator {
        @Override
        public Object evaluate(float fraction, Object startValue, Object endValue) {
            Point startPoint = (Point) startValue;
            Point endPoint = (Point) endValue;
            float x = startPoint.getX() + fraction * (endPoint.getX() - startPoint.getX());//x坐标线性变化
            float y = 120 * (float) (Math.sin(0.01 * Math.PI * x)) + getHeight() / 2;//y坐标取相对应函数值
            return new Point(x, y);
        }
 }
-- 自定义Interpolator(插值器)
public class DecelerateAccelerateInterpolator implements TimeInterpolator{
 
    @Override
    public float getInterpolation(float input) {
        float result;
        if (input <= 0.5) {
            result = (float) (Math.sin(Math.PI * input)) / 2;
        } else {
            result = (float) (2 - Math.sin(Math.PI * input)) / 2;
        }
        return result;
    }

   可以控制速度,即为Interpolator(插值),有以下几种(Interpolator的实现类):
LinearInterpolator(匀速);

AccelerateInterpolator(先慢后快);
AccelerateDecelerateInterpolator(先慢中快后慢);

DecelerateInterpolator(先快后慢);
CycleInterpolator(循环播放,速度为正弦曲线);

AnticipateInterpolator(先回撤,再匀速向前);
OvershootInterpolator(超过,拉回);

BounceInterpolator(回弹);

-- 属性动画对属性的get() set()
//1、透明度:alpha  

public void setAlpha(float alpha)  
//2、旋转度数:rotation、rotationX、rotationY  

public void setRotation(float rotation)  

public void setRotationX(float rotationX)  

public void setRotationY(float rotationY)  
//3、平移:translationX、translationY  

public void setTranslationX(float translationX)   

public void setTranslationY(float translationY)  
//4.缩放:scaleX、scaleY  

public void setScaleX(float scaleX)  

public void setScaleY(float scaleY) 

* getDuration():获取动画的持续时间。 
* getInterpolator():获取动画的时间插补器。 
* getListeners():获取监听器集合。 
* getStartDelay():获取动画延迟开始的时间。 
* setDuration(long duration):设置动画持续时间。

* setInterpolator(TimeInterpolator value):设置时间插值器。
* setStartDelay(long startDelay):设置动画延迟多少毫秒后start()方法被调用。 

* setTarget(Object target):设置目标对象。

-- 属性动画工作原理:

  创建属性动画时,每个对象都包含一个ValueAnimator,并通过监控机制AnimatorUpdateListner实时监控动画的执行,并可以计算出运行了多场时间、当前相应属性的值等,比如(X),之后,可以根据需求更新相应的对象。最直观的就是利用ObjectAnimator做动画时,目标对象需要提供相应属性的getter和setter方法,系统会根据属性的初始值和最终值,以动画的效果多次去调用set方法,随着时间的推移,set的值会越来越接近最终值。

> 制作动画 动漫(行业及产业):

  按照播出渠道可分为两种。一种是供电视台播出的动画系列片, 又称电视版动画;一种是供影院上映的动 画电影,又称剧场版动画片。

动画库 动画Demo

SurfaceView模拟火花粒子的滑动喷射效果- https://github.com/a396901990/SparkScreen/tree/master
android跳动的小球动画- https://blog.csdn.net/yoywow/article/details/52368215

Android 弹性动画的三种实现方式- https://github.com/MRYangY/SpringAnimationDemo/tree/br_temp

GIF animations gif-movie-view- https://github.com/sbakhtiarov/gif-movie-view
Android帧动画实现,防OOM,比原生动画集节约超过十倍的资源- https://github.com/ansen360/FrameAnimation

-- Lottie

 Lottie 是 airbnb 发布的库,它可以将 AE 制作的动画 在 Android&iOS上以 native 代码渲染出来,目前还支持了 RN 平台。
 Lottie本身在 Android 平台已经做了适配工作,而且适配原理很简单,解析 时,从 读取宽高之后 会再乘以手机的密度。再在使用的时候判断适配后的宽高是否超过屏幕的宽高,如果超过则再进行缩放。以此保障 Lottie 在 Android 平台的显示效果。
 有了 Lottie,只要设计师用 AE 设计动画,利用 bodymovin 导出 ,导入到 assets, 再写下面那么点代码就可以实现了!
LottieAnimationView animationView = (LottieAnimationView) findViewById(R.id.animation_view);
animationView.setAnimation("PinJump.json");
animationView.loop(true);
animationView.playAnimation();

Airbnb的开源项目lottie-android- https://github.com/airbnb/lottie-android

动画Android-gif-drawable:https://github.com/koral--/android-gif-drawable

-- giflib,gif可以看作一系列帧动画;libjpeg解码jpeg图片和libpng解码png图片
gif 格式图片详细解析- https://blog.csdn.net/wzy198852/article/details/17266507
GIFLIB- https://sourceforge.net/projects/giflib/
android app动图优化:源码giflib加载gif动图,性能秒杀glide- https://blog.csdn.net/wxk105/article/details/71698515
解决android中giflib bug手记- https://blog.csdn.net/lzf_china/article/details/4026918
Google GifView Android显示GIF动画- http://code.google.com/p/gifview/downloads/list
 

  移动应用动画效果框架 Lottie,Lottie 是一个可应用于Andriod和iOS的动画库,它通过bodymovin插件来解析Adobe After Effects 动画并导出为json文件,通过手机端原生的方式或者通过React Native的方式渲染出矢量动画。
  直接从Sketch画板生成After After Effects图层- https://google.github.io/sketch2ae/

一个使用openGL渲染的炫丽Android动画库- https://github.com/gplibs/android-magic-surface-view

动画帮助工具库 -https://github.com/Jerey-Jobs/AnimationHelper
Android 开源动画框架NineOldAndroids - https://github.com/JakeWharton/NineOldAndroids

开源项目JazzyViewPager实现ViewPager切换动画- https://github.com/jfeinstein10/JazzyViewPager

Jake Wharton的动画开源库NineOldAndroids-- https://github.com/JakeWharton/NineOldAndroids

-- ViewPager.PageTransformer,ViewPager切换动画
ViewPager切换动画PageTransformer的使用- http://blog.csdn.net/way_ping_li/article/details/12975555

ViewPager的PageTransformer属性- http://blog.csdn.net/u012702547/article/details/52334161

ViewPager切换动画PageTransformer(兼容Android3.0以下)- http://blog.csdn.net/lmj623565791/article/details/40411921


- 你所不知道的Activity转场动画ActivityOptions- http://blog.csdn.net/qibin0506/article/details/48129139
google在新的sdk中给我们提供了另外一种Activity的过度动画ActivityOptions。并且提供了兼容包ActivityOptionsCompat。

android动画案例集合- http://download.csdn.net/detail/u013043346/9374204

> 自定义动画

 最常用的动画类Animation或者Animator,其实它们内部实现也是一个“动画驱动”,驱动View不断绘制。所以,我们完全可以不用Animation或者Animator去做动画,只要有一个“驱动”即可,例如Scroller是个不错的选择,甚至我们可以写一个我们自己实现的“动画驱动”。

Android自定义Transition动画- http://blog.csdn.net/qibin0506/article/details/53248597

属性动画 示例 总结- https://www.cnblogs.com/baiqiantao/p/5410382.html

-- 属性(Property)动画,插值器(Interpolator)和估值器(TypeEvaluator),ObjectAnimator和ValueAnimator ,ViewPropertyAnimator,PropertyValuesHolder ,AnimatorSet

Android 动画系列之属性(Property)动画详解- https://blog.csdn.net/airsaid/article/details/52074566

Android属性动画完全解析(上),初识属性动画的基本用法- http://blog.csdn.net/guolin_blog/article/details/43536355
Android属性动画完全解析(中),ValueAnimator和ObjectAnimator的高级用法 - https://blog.csdn.net/guolin_blog/article/details/43816093
Android属性动画完全解析(下),Interpolator和ViewPropertyAnimator的用法- https://blog.csdn.net/guolin_blog/article/details/44171115

Android属性动画-Property Animation(一) 原理分析-- http://blog.csdn.net/nugongahou110/article/details/46701789
Android属性动画-Property Animation(二) 使用ObjectAnimator完成动画-- http://blog.csdn.net/nugongahou110/article/details/46722595
Android属性动画-Property Animation(三) 使用ValueAnimator完成动画-- http://blog.csdn.net/nugongahou110/article/details/46727297
Android属性动画-Property Animation(四) 组合动画-- http://blog.csdn.net/nugongahou110/article/details/46738069

Android 属性动画(Property Animation) 完全解析 (上)- https://blog.csdn.net/lmj623565791/article/details/38067475
Android 属性动画(Property Animation) 完全解析 (下)- https://blog.csdn.net/lmj623565791/article/details/38092093

Android 动画:你真的会使用插值器与估值器吗?(含详细实例教学)- https://blog.csdn.net/carson_ho/article/details/72863901
 TypeEvaluator估值器,告诉动画系统如何从初始值过度到结束值,TypeEvaluator类型估值算法(估值器)有IntEvaluator,FloatEvaluator,ArgbEvaluator。其中动画的默认刷新率为10ms/帧。
 ValueAnimator.ofFloat()方法就是实现了初始值与结束值之间的平滑过度

-- 自定义TypeEvaluator(估值器)
public class FloatEvaluator implements TypeEvaluator {  
    public Object evaluate(float fraction, Object startValue, Object endValue) {  
        float startFloat = ((Number) startValue).floatValue();  
        return startFloat + fraction * (((Number) endValue).floatValue() - startFloat);  
    }  

  ValueAnimator的ofFloat()和ofInt()方法,分别用于对浮点型和整型的数据进行动画操作的,ValueAnimator中还有一个ofObject()方法,是用于对任意对象进行动画操作的。
  Interpolator插值器 的主要作用是可以控制动画的变化速率,比如去实现一种非线性运动的动画效果。Android 1.0版本开始就一直存在Interpolator接口了,而之前的补间动画当然也是支持这个功能的。只不过在属性动画中新增了一个TimeInterpolator接口,这个接口是用于兼容之前的Interpolator的,这使得所有过去的Interpolator实现类都可以直接拿过来放到属性动画当中使用。使用属性动画时,系统默认的Interpolator其实就是一个先加速后减速的Interpolator,对应的实现类就是AccelerateDecelerateInterpolator。
public interface TimeInterpolator { 
    float getInterpolation(float input);  


//透明度变化动画  
    public void alpha(View view) {  
        //  1、通过调用ofFloat()方法创建ObjectAnimator对象,并设置目标对象、需要改变的目标属性名、初始值和结束值;  
        ObjectAnimator mAnimatorAlpha = ObjectAnimator.ofFloat(mImageView, "alpha", 1.0f, 0.0f);  
        //2、设置动画的持续时间、是否重复及重复次数属性;  
        mAnimatorAlpha.setRepeatMode(Animation.REVERSE);  
        mAnimatorAlpha.setRepeatCount(1);  
        mAnimatorAlpha.setDuration(1000);  
        //3、启动动画  
        mAnimatorAlpha.start();  
    }  
      
 //翻转动画,翻转360度  
    public void flip(View view) {  
        ObjectAnimator visibleToInVisable = ObjectAnimator.ofFloat(mImageView, "rotationX", 0.0f, 360.0f);  
        //设置插值器  
        visibleToInVisable.setInterpolator(new LinearInterpolator());  
        visibleToInVisable.setDuration(1000);  
        visibleToInVisable.start();  
    }  
 //缩放动画  
    public void scale(View view) {  
        Animator animator = AnimatorInflater.loadAnimator(this, R.animator.scale_anim);  
        animator.setTarget(mImageView);  
        animator.start();  
    }  
      
//平移动画  
    public void translate(View view) {  
        ObjectAnimator mAnimatorTranslateX = ObjectAnimator.ofFloat(mImageView, "translationX", 0.0f, screenWidth / 2);  
        mAnimatorTranslateX.setRepeatMode(Animation.REVERSE);  
        mAnimatorTranslateX.setRepeatCount(1);  
        mAnimatorTranslateX.setDuration(1000);  
  
        ObjectAnimator mAnimatorTranslateY = ObjectAnimator.ofFloat(mImageView, "translationY", 0.0f, screenHeight / 2);  
        mAnimatorTranslateY.setRepeatMode(Animation.REVERSE);  
        mAnimatorTranslateY.setRepeatCount(1);  
        mAnimatorTranslateY.setDuration(1000);  
  
        mAnimatorTranslateX.start();  
        mAnimatorTranslateY.start();  
    }  
//旋转动画  
    public void rotate(View view) {  
        ObjectAnimator mAnimatorRotate = ObjectAnimator.ofFloat(mImageView, "rotation", 0.0f, 360.0f);  
        mAnimatorRotate.setRepeatMode(Animation.REVERSE);  
        mAnimatorRotate.setRepeatCount(1);  
        mAnimatorRotate.setDuration(2000);  
  
        mAnimatorRotate.start();  
    }

-- View动,根据作用又分为缩放动画ScaleAnimation/移位动画TranslateAnimation / 透明度动画AlphaAnimation / 旋转动画RotateAnimation,这四个动画都继承android.view.animation下的Animation类。继承Animation的除了这四个类外,还有AnimationSet.
View动画,包名android.view.animation,基类为Animation,核心子类为TranslateAnimation,ScaleAnimation,AlphaAnimation,RotateAnimation及AnimationSet。 

AlphaAnimation animation = new AlphaAnimation(0.0f, 1.0f);
animation.setDuration(500);
btn_refresh.startAnimation(animation);
tv_load_error.startAnimation(animation);
animation.setAnimationListener(new AnimationListener() {
 @Override
 public void onAnimationStart(Animation animation) {
 }

@Override
public void onAnimationRepeat(Animation animation) {
}

@Override
public void onAnimationEnd(Animation animation) { // 动画结束时执行此方法
   btn_refresh.setVisibility(View.VISIBLE);
   tv_load_error.setVisibility(View.VISIBLE);
}
});

-- Android动画进阶—使用开源动画库nineoldandroids

/**
 Makes the TextView exactly this many pixels wide.
 You could do the same thing by specifying this number in the LayoutParams.
 @see #setMaxWidth(int)
 @see #setMinWidth(int)
 @see #getMinWidth()
 @see #getMaxWidth()
 @attr ref android.R.styleable#TextView_width
 */
@android.view.RemotableViewMethod
public void setWidth(int pixels) {
    mMaxWidth = mMinWidth = pixels;
    mMaxWidthMode = mMinWidthMode = PIXELS;

    requestLayout();
    invalidate();
}
/**
 Return the width of the your view.
 @return The width of your view, in pixels.
 */

@ViewDebug.ExportedProperty(category= layout)
public final int getWidth() {
    return mRight - mLeft;
}
    总之,TextView和Button的setWidth和getWidth干的不是同一件事情,通过setWidth无法改变控件的宽度,所以对width做属性动画没有效果,对应于属性动画的两个条件来说,本例中动画不生效的原因是只满足了条件1未满足条件2。

 -- 针对上述问题,Google告诉我们有3中解决方法:
1. 给你的对象加上get和set方法,如果你有权限的话;
2. 用一个类来包装原始对象,间接为其提供get和set方法;
3. 采用ValueAnimator,监听动画过程,自己实现属性的改变;

--  Button 500S从1到100
private void performAnimate(finalView target, final int start, final int end) {

    ValueAnimator valueAnimator = ValueAnimator.ofInt(1,100);
    valueAnimator.addUpdateListener(newAnimatorUpdateListener() {
        //持有一个IntEvaluator对象,方便下面估值的时候使用
        private IntEvaluator mEvaluator = new IntEvaluator();

        @Override
        public void onAnimationUpdate(ValueAnimator animator) {
            //获得当前动画的进度值,整型,1-100之间
            int currentValue = (Integer)animator.getAnimatedValue();
            Log.d(TAG,current value:  + currentValue);


            //计算当前进度占整个动画过程的比例,浮点型,0-1之间
            float fraction = currentValue / 100f;
       
            //直接调用整型估值器通过比例计算出宽度,然后再设给Button
            target.getLayoutParams().width = mEvaluator.evaluate(fraction, start, end);
            target.requestLayout();
        }
    });
    valueAnimator.setDuration(5000).start();
}

@Override
public void onClick(View v) {
    if(v == mButton) {
        performAnimate(mButton,mButton.getWidth(), 500);
    }
}


-- 属性动画继承关系:Animator(属性动画的基类)→ValueAnimator→ObjectAnimator如何使用:
1.调用ObjectAnimator的静态工厂方法创建动画(ofInt、ofFloat、ofObject)
2.调用SetXxx()设置动画持续时间、插值方式、重复次数等。
3.监听事件
4.调用Animator对象的start()方法启动动画


//标准示范,单个动画属性(ObjectAnimator)执行
public void move1(View view){
    //直接调用ObjectAnimator的工厂方法(静态方法),可以创建ObjectAnimator实例
    //前2个参数分别要指定:操作的具体的对象、操作的对象的属性。本例中,具体对象为ImageView,属性为X轴位移
    //第3个参数,是操作的对象的属性,其动画变化的范围的。本例中,X轴位移:0f~200f
    ObjectAnimator.ofFloat(mImageView, "translationX", 0f,200f)
        .setDuration(2000)
        .start();
}

//同一个对象设置多个属性动画,会同时执行。可见,属性动画实例调用start方法后,是一个异步的过程
public void move2(View view){
    ObjectAnimator.ofFloat(mImageView, "translationX", 0f,200f).setDuration(2000).start();
    ObjectAnimator.ofFloat(mImageView, "translationY", 0f,200f).setDuration(2000).start();
    ObjectAnimator.ofFloat(mImageView, "rotation", 0f,360f).setDuration(2000).start();
}

//(多个动画同时时推荐),使用PropertyValuesHolder,先将多个属性动画hold住,再一起开启动画,可以实现同样的效果。如此做法对动画进行了优化,使用多个属性的时候,更加节省系统资源。
public void move3(View view){
    PropertyValuesHolder p1 = PropertyValuesHolder.ofFloat("translationX", 0f,200f);
    PropertyValuesHolder p2 = PropertyValuesHolder.ofFloat("translationY", 0f,200f);
    PropertyValuesHolder p3 = PropertyValuesHolder.ofFloat("rotation", 0f,360f);
    ObjectAnimator.ofPropertyValuesHolder(mImageView, p1,p2,p3).setDuration(2000).start();
}

//(多个动画需求不同时时推荐),利用AnimatorSet,组合多个Animation,可以对多个动画属性进行顺序控制
//同时执行:set.playTogether(animator1,animator2,animator3)
//顺序执行:set.playSequentially(animator1,animator2,animator3)
//分布执行:play().with(); play().after();
public void move4(View view){
    ObjectAnimator animator1 = ObjectAnimator.ofFloat(mImageView, "translationX", 0f,200f);
    ObjectAnimator animator2 = ObjectAnimator.ofFloat(mImageView, "translationY", 0f,200f);
    ObjectAnimator animator3 = ObjectAnimator.ofFloat(mImageView, "rotation", 0f,360f);
    AnimatorSet set = new AnimatorSet();
    set.play(animator1).with(animator2);
    set.play(animator3).after(animator1);
    set.setDuration(1000).start();
}

> 从属性动画框架可以知:想要合理的使用属性动画,必须正确的利用动画的几大元素:动画执行类、动画监听、估值器、插值器,合理的属性动画工具能够帮助我们更加方便的达成目标。

1) 利用ValueAnimator实现属性动画:
  第一步:通过 ValueAnimator静态方法获取对象ofInt(), ofFloat(),or ofObject().,并设置动画持续时长。
  ValueAnimator animation = ValueAnimator.ofFloat(0f, 1f);
  animation.setDuration(1000);

  第二步:设置实时监听。ValueAnimator.AnimatorUpdateListener并实现其onAnimationUpdate() 。在该函数中,可以获取动画进度、以及属性的实时值,但该实时值并未直接作用于任何对象,如果想要作用于某个对象,必须用于将属性值实时设置到对象。 在onAnimationUpdate() 内部,可以通过 getAnimatedValue(). 获取当前计算到的值,之后通过对象的set等方法,实时更新对象,比如 setAlpha() 等:
 animation.addUpdateListener(new AnimatorUpdateListener() {  
        @Override  
        public void onAnimationUpdate(ValueAnimator animator) {  
             float currentValue = (Integer)animator.getAnimatedValue();  
              //计算当前进度占整个动画过程的比例,浮点型,0-1之间  然后再设给Object(比如View) 
               targetView.setAlpha(currentValue ); 
   }  
}); 
 
第三步:执行动画,之后ValueAnimator 就开始利用估值器已经插值器计算属性值,并实时利用监听接口更新对象。
  animation.start();

2) 利用ObjectAnimator实现属性动画
第一步:利用ObjectAnimator静态方法构造对象,同时要制定target对象、以及要操作的属性,比如:不透明度(alpha):
  ObjectAnimator anim = ObjectAnimator.ofFloat(foo, "alpha", 0f, 1f);
anim.setDuration(1000);
第二步:执行动画
  anim.start();
但是,由于ObjectAnimator会利用对象的setter方法自动更新相应的属性,该对象必须具有setter方法,如果实现动画的时候没有传递初始值,那么还要提供getter方法,否则无法更新。例如:属性是color,则必须具有setterColor/getterColor方法,否则动画无效。如果不存在相应属性的操作方法,则可以通过wrapper 方式间接为其提供getter和setter方法。例如:View没有直接设置宽度的方法width,可以利用wrapper实现setWidth,getWidth:

public class ViewWrapper {  
    private View mTarget;  
    public ViewWrapper(View target) {  
        mTarget = target;  
  }  
 
public int getWidth() {  
        return mTarget.getLayoutParams().width;  
    }  
 
public void setWidth(int width) {  
        mTarget.getLayoutParams().width = width;  
        mTarget.requestLayout();  
    }  }  
之后便可使用该封装类进行属性动画:
  private void performAnimate(View view) {  
    ViewWrapper wrapper = new ViewWrapper(view);  
    ObjectAnimator.ofInt(wrapper, "width", 500).setDuration(5000).start();  
  }  

3) 利用AnimatorSet实现属性动画
开发中,经常会遇到这种情形:播放一个动画依赖另一个动画是否播放完成。在属性动画中框架中,可以利用AnimatorSet构造属性动画集,来整合多个动画的播放,控制动画的并发、顺序逻辑等。AnimatorSet是Animator的子类,不仅可以作为动画使用,而且可以实现嵌套。使用方法:

ObjectAnimator anim1= ObjectAnimator.ofFloat(foo, "alpha" …);
ObjectAnimator anim2= ObjectAnimator.ofFloat(foo, "x" …);
ObjectAnimator anim3= ObjectAnimator.ofFloat(foo, "y" … );
ObjectAnimator anim4= ObjectAnimator.ofFloat(foo, …);
ObjectAnimator anim5= ObjectAnimator.ofFloat(foo, …);
 
AnimatorSet bouncer = new AnimatorSet();
bouncer.play(anim1).before(anim2);
bouncer.play(anim2).with(anim3);
bouncer.play(anim3).with(anim4);
bouncer.play(bounceBackAnim).after(stretchAnim2);
 
//集合与元素的嵌套使用
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(bouncer).before(anim5);
animatorSet.start();
}

4) 利用LayoutTransition 实现布局属性动画:
  属性动画允许布局通过动画来显示变化,比如新View元素添加到LinearLayout中时,新元素可以定义显示动画,旧元素可以定义移动动画,布局动画更像是childViews属性动画集。布局属性动画主要包含以下几种元素:

o   APPEARING  新添加的View本身的出现动画;
o   DISAPPEARING View消失动画;
o   CHANGE_APPEARING 由于新增了其他View而需要改变位置的动画;
o   CHANGE_DISAPPEARING 由于移除了其他View而需要改变位置的动画。

private void setupTransition(LayoutTransition transition) {
 
               customDisappearingAnim = ObjectAnimator.ofFloat(null, "rotationX", 0f, 90f)
               customAppearingAnim = ObjectAnimator.ofFloat(null, "rotationY", 90f, 0f)
               
               transition.setAnimator(LayoutTransition.DISAPPEARING, customDisappearingAnim);
               transition.setAnimator(LayoutTransition.CHANGE_APPEARING, customChangingAppearingAnim);
               transition.setAnimator(LayoutTransition. APPEARING , customAnimCB);    
               transition.setAnimator(LayoutTransition.CHANGE_APPEARING, customChangingAppearingAnim);
}
5) 利用XML实现属性动画。
  同视图动画类似,属性动画也可利用XML定义,不过放置的位置与视图动画不同,属性动画的XML文件放在res/animator目录下。XML属性动画的使用分两步

第一步:定义相应动画
<set android:ordering="sequentially">
    <set>
        <objectAnimator
            android:propertyName="x"
            android:duration="500"
            android:valueTo="400"
            android:valueType="intType"/>
        <objectAnimator
            android:propertyName="y"
            android:duration="500"
            android:valueTo="300"
            android:valueType="intType"/>
    </set>
    <objectAnimator
        android:propertyName="alpha"
        android:duration="500"
        android:valueTo="1f"/>
</set>

第二步:在Java代码中利用AnimatorInflater加载,渲染既可
 AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext, R.anim.property_animator);
set.setTarget(myObject);
set.start();

动画的应用:http://www.mamicode.com/info-detail-1150209.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值