zoukankan      html  css  js  c++  java
  • 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

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

  • 相关阅读:
    react ts axios 配置跨域
    npm run eject“Remove untracked files, stash or commit any changes, and try again.”错误
    java 进程的参数和list的线程安全
    帆软报表 大屏列表跑马灯效果JS
    帆软报表 快速复用数据集,避免重复劳动
    分析云 OA中部门分级思路和实现方法
    分析云 分段器 只显示一个块的数据
    分析云 更改服务默认的端口号
    分析云U8项目配置方法新版本(2)
    Oracle 创建时间维度表并更新是否工作日字段
  • 原文地址:https://www.cnblogs.com/blfshiye/p/4645454.html
Copyright © 2011-2022 走看看