• Android Property Animation 物业动画


    效果图:
     

    Property Animation介绍: 

    出生在sdk3.0,是利用了View所拥有的属性,进行一系列的操作。

    比方一个View有什么样的setAbc的属性,那么理论上就能够设置它。

    它不仅改变View的绘制,也改变了View的属性;而Tween Animation 仅仅改变View的绘制。

    Animator为属性动画的基类

      其结构:

    Animator abstract class

       ---- AnimatorSet final class 属性动画的集合,能够加入以下的值动画和对象对象在其内。可同一时候执行或顺序执行

       ----ValueAnimator 值动画。监听某一值的变化,进行对应的操作

          ---- ObjectAnimator final class 对象动画

    ValueAnimator 值动画,它有一个子类ObjectAnimator。

    须要Interpolator和TypeEvaluator来计算属性值。

    TimeInterpolator 时间插入器 接口,反应动画的运动速率。

    getInterpolation()依据一定算法,返回时间比率

       ----Interpolator interface 继承自TimeInterpolator

       Interpolator 接口的实现类 见下表:


        xml 设置 插入器:android:interpolator="@android:anim/accelerate_decelerate_interpolator"


    TypeEvaluator<T> interface 计算类型值 支持泛型

         方法:T evaluate(float fraction, T startValue, T endValue)

       就是用来计算属性值的,就可以计算随意类型的值。

       fraction 表示时间的比率。

       实现类有: ArgbEvaluator ARGB颜色计算器

       FloatEvaluator float型计算器

       IntEvaluator int计算器

    PropertyValuesHolder 属性值持有者  持有属性名、開始与结束值。

          属性设置方法:setIntValues()、setFloatValues()、setObjectValues()、setKeyframes

          它的静态的一些of方法,创建 PropertyValuesHolder 对象。 ofInt、ofFloat、ofObject、ofKeyframe

          setEvaluator(eval); //设置计算器。


    Keyframe  表示 a time/frame-value pair. 即含有 时间比率和帧值 属性

          它的静态的一些of方法,创建 Keyframe 对象。  ofInt、ofFloat、ofObject

    KeyframeSet 就是一组KeyFrame

                它的静态的一些of方法。创建 KeyframeSet 对象。  ofInt、ofFloat、ofObject、ofKeyframe


    属性动画的一些说明:
    1. ObjectAnimator 对象动画,当一个view同一时候拥有某一属性的getter、setter方法时,则能够使用该动画,来操作这一属性。
    2. ValueAnimator 操作的范围比較广。通过Interpolator和TypeEvaluator得到某一时间内的值;再用监听器,监听值的变化,做对应的操作。
    3. ValueAnimator 和ObjectAnimator(它是前者的子类)的静态的一些of方法。创建自身对象。
       也能够new 一个无參的对象。再设置对应的values。
       ofInt()、ofFloat()、ofObject()、ofPropertyValuesHolder()。
         这几个方法的实现也就是new 一个无參的对象。再设置对应的values。

    4. ValueAnimator 的调用流程: a. 初始化ValueAnimator后,设置一个values。这时就有了一个PropertyViewHolder对象pvh。 能够直接调用setValues设置它PVH对象;或setInt|Float|ObjectValues 方法内部会生成一个PVH PVH内部维护一个KeyframeSet和TypeEvaluator。PVH依据不同的values来初始化KeyframeSet和 TypeEvaluator实现方法中的startValue和endValue就从KeyframeSet中的Keyframe中获取 b. 设置TypeEvaluator。传递到pvh中。 c. 设置Interpolator。 ValueAnimator中默认的插入器为AccelerateDecelerateInterpolator d. ValueAnimator的animationFrame(long currentTime),当有动画应该结束时返回true,否则返回false。

    方法内,算出动画执行的时间比率fraction,再调用animateValue(float fraction)。

    e. ValueAnimator的animateValue(float fraction)。调用插入器,得到一个按某一规则得到的fraction, 再调用 pvh.calculateValue(fraction);pvh调用KeyframeSet的getValue(fraction)。 KeyframeSet内部再调用TypeEvaluator的evaluate(fraction,T startValue, T endValue)。 startValue、endValue是通过Keyframe的getValue()来获取的。 f. evaluate(),方法内拿到了时间比率fraction,能够自行依据一定规则。返回value T。 g. 给ValueAnimator加入一个AnimatorUpdateListener。监听的回调方法: onAnimationUpdate(ValueAnimator animation) { T obj = (T)animation.getAnimatedValue();//取得计算器计算出的某段时间内的T值。

    // 操作 obj }




    先来一个使用自己定义类型的求值计算器的ValueAnimator的样例

    	ValueAnimator backAnim;
    	ImageView view;
    
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		
    		setContentView(R.layout.aa);
    		
    		view = (ImageView) findViewById(R.id.iv_img); 
    		
    		backAnim = new ValueAnimator();
    		backAnim.setTarget(view);
    		backAnim.setDuration(2000);
    		
    		//类型求值<Drawable>:求出某一时间比值内的Drawable值 
    		TypeEvaluator<Drawable> drawableEvaluator = new TypeEvaluator<Drawable>() {
    		
    			@Override  //fraction 当前执行的时间比上总持续时间的 比值(中间经过插入器的规则运算)
    			public Drawable evaluate(float fraction, Drawable startValue,
    					Drawable endValue) {
    				System.out.println(fraction);
    				if (fraction < 0.5) {
    					return startValue;
    				} else {
    					return endValue;
    				}
    			}
    		};
    		
    		//能够直接设置PVH对象。也能够先设置values,再设置TypeEvaluator
    //		PropertyValuesHolder pvh = PropertyValuesHolder.ofObject("imageDrawable", drawableEvaluator, 
    //				 getResources().getDrawable(R.drawable.ic_launcher), getResources().getDrawable(R.drawable.a1));
    //		backAnim.setValues(pvh);
    		backAnim.setObjectValues(getResources().getDrawable(R.drawable.ic_launcher), getResources().getDrawable(R.drawable.a2));
    		backAnim.setEvaluator(drawableEvaluator);
    		
    		backAnim.addUpdateListener(new AnimatorUpdateListener() {
    			
    			@Override
    			public void onAnimationUpdate(ValueAnimator animation) {
    				Drawable value = (Drawable) animation.getAnimatedValue();
    				view.setImageDrawable(value);
    			}
    		});
    		backAnim.setInterpolator(new CycleInterpolator(2));
    		backAnim.start();
    	}
    

    3.0以后新增了一些View的属性:

    1)translationX 和 translationY:这两个属性控制了View所处的位置,
         它们的值是由layout容器设置的,是相对于坐标原点(0,0左上角)的一个偏移量。

    2)rotation, rotationX 和 rotationY:控制View绕着轴点(pivotX和pivotY)旋转。它的表现跟Tween Animation中的RotateAnimation不一致。

    RotateAnimation 的旋转,表现为平面的旋转

         而rotationX、Y 旋转。是立体的旋转,默认是以View的中心点。做rotation(x,y)过中心点的直线。面向该直线进行翻转
    3)scaleX 和 scaleY:控制View基于pivotX和pivotY的缩放。
    4)pivotX 和 pivotY:旋转的轴点和缩放的基准点,默认是View的中心点。


    5)x 和 y:描写叙述了view在其父容器中的终于位置,是左上角坐标和偏移量(translationX。translationY)的和。
    6)aplha:透明度,1是全然不透明,0是全然透明。

    以上这些属性与Tween Animation的动画属性值差点儿相同


    ObjectAnimator 对象动画

    该动画。一次仅仅能表示一个动作属性。

    ObjectAnimator的xml实现

    xml定义动画

    res/animator/scale_object_animator.xml

    <?xml version="1.0" encoding="utf-8"?>
    <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="2000"
        android:propertyName="scaleX"
        android:repeatCount="1"
        android:repeatMode="reverse"
        android:valueFrom="1.0"
        android:valueTo="2.0" >
    
    </objectAnimator>

    代码载入 动画xml

    imageview_scale.setBackground(getResources().getDrawable(R.drawable.a11));
    		ObjectAnimator scaleAnimator = (ObjectAnimator) AnimatorInflater.loadAnimator(this, R.animator.scale_object_animator);
    		scaleAnimator.setTarget(imageview_scale);//设置动画作用的目标对象
    		scaleAnimator.setDuration(1000);
    		scaleAnimator.setRepeatCount(50);
    		scaleAnimator.start();

    AnimatorSet 动画集

    由ObjectAnimator 和 ValueAnimator 组成,相应的xml中的写法 类似为 <set> <objectAnimator /> ... <animator />... </set>

    xml定义动画集

    res/animator/set_rotate_scale.xml

    <?xml version="1.0" encoding="utf-8"?

    > <set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="together"> <!-- android:ordering together表示同一时候执行动画, sequentially 表示按顺序执行下面动画 --> <set> <objectAnimator android:propertyName="rotationX" android:repeatCount="50" android:repeatMode="reverse" android:valueFrom="0" android:valueTo="20" /> <objectAnimator android:propertyName="rotationY" android:repeatCount="50" android:repeatMode="reverse" android:valueFrom="0" android:valueTo="45" android:valueType="floatType" /> </set> <set> <objectAnimator android:propertyName="scaleX" android:repeatCount="50" android:repeatMode="reverse" android:valueFrom="1.0" android:valueTo="2.0" > </objectAnimator> <objectAnimator android:propertyName="scaleY" android:repeatCount="50" android:repeatMode="reverse" android:valueFrom="1.0" android:valueTo="2.0" > </objectAnimator> </set> </set>


    
    

    代码载入 动画集的xml

    imageview_rotate.setBackground(getResources().getDrawable(R.drawable.a11));
    		AnimatorSet animatorSet = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.set_rotate_scale);
    		animatorSet.setTarget(imageview_rotate);
    		animatorSet.setDuration(1000);
    		animatorSet.setInterpolator(new BounceInterpolator());//设置end时的弹跳插入器
    		animatorSet.start();

    PropertyValuesHolder

    //使用PropertyValuesHolder 构造 Animator   组合成相似set的效果
    		PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("scaleX",0f,2.5f);
    		PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("scaleY",0f,3f);     
    		ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(imageview, pvhX,pvhY);
    		animator.setDuration(2000);
    		animator.start();

    APIDemo中的MultiPropertyAnimation演示样例:

      // ============================================================
                    // 第四个小球:利用关键帧实现曲线运动
                    ball = balls.get(3);
                    // 属性1:Y坐标运动:下落
                    pvhY = PropertyValuesHolder.ofFloat("y", ball.getY(),
                            getHeight() - BALL_SIZE);
                    float ballX = ball.getX();
                    // 三个关键帧
                    Keyframe kf0 = Keyframe.ofFloat(0f, ballX); //參数为 time/value, 即时间点和指定值。还有这些构造ofInt()、ofObject()
                    Keyframe kf1 = Keyframe.ofFloat(.5f, ballX + 100f);
                    Keyframe kf2 = Keyframe.ofFloat(1f, ballX + 50f);
                    // 属性2:X坐标运动:曲折
                    // 用三个关键帧构造PropertyValuesHolder对象
                    PropertyValuesHolder pvhX = PropertyValuesHolder.ofKeyframe(
                            "x", kf0, kf1, kf2);
    
                    // 再用两个PropertyValuesHolder对象构造一个ObjectAnimator对象。

    <span style="color:#ff6666;">一个holder持有一个属性</span> ObjectAnimator yxBouncer = ObjectAnimator .ofPropertyValuesHolder(ball, pvhY, pvhX).setDuration( DURATION / 2); yxBouncer.setRepeatCount(1); yxBouncer.setRepeatMode(ValueAnimator.REVERSE);



    ViewPropertyAnimator 多属性动画

    通过view.animate()来获取ViewPropertyAnimator。该类。能直接操作多个属性的动画。

    imageview.setBackground(getResources().getDrawable(R.drawable.a11));
    		ViewPropertyAnimator animate = imageview.animate();//该对象没有setRepeat的方法
    		//通过一些动画属性来设置 组合成相似set的效果
    		animate.alpha(0);
    		animate.rotationX(50);
    		animate.translationXBy(500);
    		animate.scaleX(1.5f);
    		animate.scaleY(1.5f);
    		animate.setInterpolator(new BounceInterpolator());
    		animate.setDuration(2000);
    		animate.start();

    ValueAnimator 值动画

    ValueAnimator代码和xml设置中 没有setPropertyName 由于不是操作对象,仅仅是依据value进行某种动作
    须要加监听器,监听值的变化 做对应的处理

    xml定义值动画

    <?xml version="1.0" encoding="utf-8"?>
    <animator xmlns:android="http://schemas.android.com/apk/res/android" 
        android:interpolator="@android:anim/accelerate_interpolator"
        android:duration="10000"
        android:startOffset="1000"
        android:repeatCount="infinite"
        android:repeatMode="restart"
        android:valueFrom="1"
        android:valueTo="100"
        android:valueType="intType">
    
    </animator>
    

    代码载入 值动画xml

    ValueAnimator valueAnimator = (ValueAnimator) AnimatorInflater.loadAnimator(this, R.animator.animator);
    		valueAnimator.setTarget(tv_num);
    		valueAnimator.setEvaluator(new TypeEvaluator<Integer>() {
    
    			@Override 
    			public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
    				System.out.println("时间比率。fraction:" + fraction);
    				System.out.println("结果值:" + (int)((startValue + fraction * (endValue - startValue)) / 10 * 10));
    			    return (int)((startValue + fraction * (endValue - startValue)) / 10 * 10);
    			}
    		});
    		valueAnimator.addUpdateListener(new AnimatorUpdateListener() {
    			
    			@Override
    			public void onAnimationUpdate(ValueAnimator animation) {
    				//在onAnimationUpdate中 该值返回第一个动画的 当前帧的evaluate 值
    				System.out.println("animation.getAnimatedValue()==" + animation.getAnimatedValue());
    				tv_num.setText(animation.getAnimatedValue() + "");
    			}
    		});
    //		valueAnimator.setInterpolator(new LinearInterpolator());
    		valueAnimator.start();

    Animator的监听器

    AnimatorListener

    new AnimatorListener() {//有下面四个抽象方法
    			
    			@Override
    			public void onAnimationStart(Animator animation) {
    				
    			}
    			
    			@Override
    			public void onAnimationRepeat(Animator animation) {
    				
    			}
    			
    			@Override
    			public void onAnimationEnd(Animator animation) {
    				
    			}
    			
    			@Override
    			public void onAnimationCancel(Animator animation) {
    				
    			}
    		}

    AnimatorListenerAdapter 监听器的默认空实现

    new AnimatorListenerAdapter() {//空实现了AnimatorListener。有下面6个方法(4个必须实现的方法和2个重写的方法)
    
    			@Override
    			public void onAnimationCancel(Animator animation) {
    				super.onAnimationCancel(animation);
    			}
    
    			@Override
    			public void onAnimationEnd(Animator animation) {
    				super.onAnimationEnd(animation);
    			}
    
    			@Override
    			public void onAnimationRepeat(Animator animation) {
    				super.onAnimationRepeat(animation);
    			}
    
    			@Override
    			public void onAnimationStart(Animator animation) {
    				super.onAnimationStart(animation);
    			}
    
    			@Override
    			public void onAnimationPause(Animator animation) {
    				super.onAnimationPause(animation);
    			}
    
    			@Override
    			public void onAnimationResume(Animator animation) {
    				super.onAnimationResume(animation);
    			}
    			
    		}

    AnimatorUpdateListener 动画的值更新监听器

    new AnimatorUpdateListener() {
    			
    			@Override
    			public void onAnimationUpdate(ValueAnimator animation) {
    				//在onAnimationUpdate中 该值返回第一个动画的 当前帧的evaluate 值
    				System.out.println("animation.getAnimatedValue()==" + animation.getAnimatedValue());
    			}
    }

    一些操作函数:

        animator.pause();  animator.resume(); animator.reverse(); animator.end(); animator.cancel();

        animator.start(); animator.isStarted(); animator.isPaused(); animator.isRunning();


    用属性动画换背景色

    详见ApiDemo要下的 BouncingBalls.java

    private static final int RED = 0xffFF8080;
    private static final int BLUE = 0xff8080FF;
    private static final int CYAN = 0xff80ffff;
    private static final int GREEN = 0xff80ff80;
    
    {
    	//动画 变色  
    	ObjectAnimator colorAnim = ObjectAnimator.ofInt(this, "backgroundColor", CYAN, BLUE, RED);
    	colorAnim.setTarget(ll_animation);
    	colorAnim.setEvaluator(new ArgbEvaluator());
    	colorAnim.setRepeatCount(ValueAnimator.INFINITE);
    	colorAnim.setRepeatMode(ValueAnimator.REVERSE);
    	colorAnim.setDuration(3000);
    	colorAnim.start();
    }

    LayoutTransition

    /*
    		 * ViewGroup中使用LayoutTransition 进行 监听布局的改变。而创建动画
    		 * LayoutTransition.APPEARING 新增出现时
    		 *                  CHANGE_APPEARING 
    		 *                  CHANGE_DISAPPEARING 子view消失时
    		 *                  CHANGING
    		 * ViewGroup布局中:android:animateLayoutChanges="true"  使用的默认的LayoutTransition制作动画
    		 */
    		LayoutTransition layoutTransition = new LayoutTransition();
    		layoutTransition.setDuration(5000);
    		layoutTransition.setAnimator(LayoutTransition.APPEARING, scaleAnimator);
    		ll_animation.setLayoutTransition(layoutTransition);
    		
    		final TextView tv = new TextView(this);
    		tv.setWidth(100);
    		tv.setHeight(100);
    		tv.setText("中华人民共和国");
    		ll_animation.addView(tv);//相应type = APPEARING
    		
    		ll_animation.postDelayed(new Runnable() {
    			
    			@Override
    			public void run() {
    				ll_animation.removeView(tv);
    			}
    		}, 2000);

       參考样例见:ApiDemos下的  LayoutAnimations.java

    版权声明:本文博客原创文章,博客,未经同意,不得转载。

  • 相关阅读:
    CAS简介
    Volatile的3大特性
    dsf对矩阵进行搜索
    JVM
    REST风格
    自定义Starters(自动配置Bean)
    反射和注解的原理
    mybatis的注解开发
    Java的多线程安全
    mybatis(3)
  • 原文地址:https://www.cnblogs.com/blfshiye/p/4645454.html
Copyright © 2020-2023  润新知