登录 立即注册
安币:

楼主: liujh

Android动画解析(二)

[复制链接]

215

主题

216

帖子

4590

安币

手工艺人

发表于 2018-4-13 10:45:01 | 显示全部楼层 |阅读模式
如果对本篇文章感兴趣,请前往,原文地址:http://www.apkbus.com/blog-847095-77492.html

一、插值器和估值器:

Interpolator(插值器)和TypeEvaluator(估值器)是实现非匀速动画的重要手段
1、Interpolator: 过渡值变化的规则( 控制动画的进度 )




  • * AccelerateDecelerateInterpolator   在动画开始与介绍的地方速率改变比较慢,在中间的时候加速  
  • * AccelerateInterpolator                     在动画开始的地方速率改变比较慢,然后开始加速  
  • * AnticipateInterpolator                      开始的时候向后然后向前甩  
  • * AnticipateOvershootInterpolator     开始的时候向后然后向前甩一定值后返回最后的值  
  • * BounceInterpolator                          动画结束的时候弹起  
  • * CycleInterpolator                             动画循环播放特定的次数,速率改变沿着正弦曲线  
  • * DecelerateInterpolator                    在动画开始的地方快然后慢  
  • * LinearInterpolator                            以常量速率改变  
  • * OvershootInterpolator                      向前甩一定值后再回到原来位置  

        * AccelerateDecelerateInterpolator   在动画开始与介绍的地方速率改变比较慢,在中间的时候加速        * AccelerateInterpolator                     在动画开始的地方速率改变比较慢,然后开始加速        * AnticipateInterpolator                      开始的时候向后然后向前甩        * AnticipateOvershootInterpolator     开始的时候向后然后向前甩一定值后返回最后的值        * BounceInterpolator                          动画结束的时候弹起        * CycleInterpolator                             动画循环播放特定的次数,速率改变沿着正弦曲线        * DecelerateInterpolator                    在动画开始的地方快然后慢        * LinearInterpolator                            以常量速率改变        * OvershootInterpolator                      向前甩一定值后再回到原来位置2、自定义插值器:
实现TimeInterpolator。TimeInterpolator:时间插值器,根据时间的百分比计算属性改变的百分比







  • class MyInterploator implements TimeInterpolator{  
  •      @Override  
  •      public float getInterpolation(float input) {  
  •          return 1-input;  
  •      }  
  • }  

   class MyInterploator implements TimeInterpolator{        @Override        public float getInterpolation(float input) {            return 1-input;        }    }在getInterpolation函数中,直接把input值返回,即以当前动画的进度做为动画的数值进度,这也就表示当前动画的数值进度与动画的时间进度一致
3、evaluator  估值器
将从加速器返回的数字进度转成对应的数字值。
通过在AnimatorUpdateListener监听器使用animation.getAnimatedValue()函数拿到Evaluator中返回的数字值。
ofInt()对应的Evaluator类名叫IntEvaluator,而ofFloat()对应的Evaluator类名叫FloatEvaluator;




  • public class IntEvaluator implements TypeEvaluator<Integer> {  
  •   
  •     /**
  •      * This function returns the result of linearly interpolating the start and end values, with
  •      * <code>fraction</code> representing the proportion between the start and end values. The
  •      * calculation is a simple parametric calculation: <code>result = x0   t * (v1 - v0)</code>,
  •      * where <code>x0</code> is <code>startValue</code>, <code>x1</code> is <code>endValue</code>,
  •      * and <code>t</code> is <code>fraction</code>.
  •      *
  •      * @param fraction   The fraction from the starting to the ending values
  •      * @param startValue The start value; should be of type <code>int</code> or
  •      *                   <code>Integer</code>
  •      * @param endValue   The end value; should be of type <code>int</code> or <code>Integer</code>
  •      * @return A linear interpolation between the start and end values, given the
  •      *         <code>fraction</code> parameter.
  •      */  
  •     public Integer evaluate(float fraction, Integer startValue, Integer endValue) {  
  •         int startInt = startValue;  
  •         return (int)(startInt   fraction * (endValue - startInt));  
  •     }  
  • }  

public class IntEvaluator implements TypeEvaluator<Integer> {    /**     * This function returns the result of linearly interpolating the start and end values, with     * <code>fraction</code> representing the proportion between the start and end values. The     * calculation is a simple parametric calculation: <code>result = x0   t * (v1 - v0)</code>,     * where <code>x0</code> is <code>startValue</code>, <code>x1</code> is <code>endValue</code>,     * and <code>t</code> is <code>fraction</code>.     *     * @param fraction   The fraction from the starting to the ending values     * @param startValue The start value; should be of type <code>int</code> or     *                   <code>Integer</code>     * @param endValue   The end value; should be of type <code>int</code> or <code>Integer</code>     * @return A linear interpolation between the start and end values, given the     *         <code>fraction</code> parameter.     */    public Integer evaluate(float fraction, Integer startValue, Integer endValue) {        int startInt = startValue;        return (int)(startInt   fraction * (endValue - startInt));    }}fraction就是加速器中的返回值,表示当前动画的数值进度,百分制的小数表示。
startValue和endValue分别对应ofInt(int start,int end)中的start和end的数值;
4、自定义估值器:




  • public class MyEvaluator implements TypeEvaluator<Integer> {   
  •        @Override   
  •        public Integer evaluate(float fraction, Integer startValue, Integer endValue) {  
  •            int startInt = startValue;  
  •            return (int)(200 startInt   fraction * (endValue - startInt));  
  •        }   
  • }  

        public class MyEvaluator implements TypeEvaluator<Integer> {          @Override          public Integer evaluate(float fraction, Integer startValue, Integer endValue) {            int startInt = startValue;            return (int)(200 startInt   fraction * (endValue - startInt));        }          }5、ArgbEvalutor  颜色过度的估值器




  • ValueAnimator animator = ValueAnimator.ofInt(0xffffff00, 0xff0000ff);  
  • animator.setEvaluator(new ArgbEvaluator());  
  • animator.setDuration(3000);  
  •    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener(){  
  •        @Override  
  •        public void onAnimationUpdate (ValueAnimator animation){  
  •            int curValue = (int) animation.getAnimatedValue();  
  •            tv.setBackgroundColor(curValue);  
  •         }  
  •    });  
  •    animator.start();  

ValueAnimator animator = ValueAnimator.ofInt(0xffffff00, 0xff0000ff);        animator.setEvaluator(new ArgbEvaluator());        animator.setDuration(3000);    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener(){        @Override        public void onAnimationUpdate (ValueAnimator animation){            int curValue = (int) animation.getAnimatedValue();            tv.setBackgroundColor(curValue);         }    });    animator.start();三、ObjectAnimator
继承于ValueAnimator
public static ObjectAnimator ofFloat(Object target, String propertyName, float... values)
public static ObjectAnimator ofInt(Object target, String propertyName, int... values)
public static ObjectAnimator ofObject(Object target, String propertyName,TypeEvaluator evaluator, Object... values)

  • 第一个参数用于指定这个动画要操作的是哪个控件
  • 第二个参数用于指定这个动画要操作这个控件的哪个属性
  • 第三个参数是可变长参数,这个就跟ValueAnimator中的可变长参数的意义一样了,就是指这个属性值是从哪变到哪。

1、属性动画的原理:
object必须提供该属性的set方法,多次调用set方法,每次传给set的值不一样。
如果没初始值,还需要get方法,因为系统要获取属性的初始值。
例如:




  • ObjectAnimator animator = ObjectAnimator.ofFloat(tv,"rotation",0,180,0);  

ObjectAnimator animator = ObjectAnimator.ofFloat(tv,"rotation",0,180,0);ObjectAnimator在做动画时就会到指定控件(TextView)中去找对应的setRotation()方法来改变控件中对应的值。




  • public void setRotation(float rotation) {  
  •     if (rotation != getRotation()) {  
  •         // Double-invalidation is necessary to capture view's old and new areas  
  •         invalidateViewProperty(true, false);  
  •         mRenderNode.setRotation(rotation);  
  •         invalidateViewProperty(false, true);  
  •   
  •         invalidateParentIfNeededAndWasQuickRejected();  
  •         notifySubtreeAccessibilityStateChangedIfNeeded();  
  •     }  
  • }  

public void setRotation(float rotation) {    if (rotation != getRotation()) {        // Double-invalidation is necessary to capture view's old and new areas        invalidateViewProperty(true, false);        mRenderNode.setRotation(rotation);        invalidateViewProperty(false, true);        invalidateParentIfNeededAndWasQuickRejected();        notifySubtreeAccessibilityStateChangedIfNeeded();    }}调用的内部进行属性调整,通过invalidate进行重绘。



View关于动画的set方法如下:
//透明度:alpha
public void setAlpha(float alpha)


//旋转度数:rotation、rotationX、rotationY
public void setRotation(float rotation)
public void setRotationX(float rotationX)
public void setRotationY(float rotationY)


//平移:translationX、translationY
public void setTranslationX(float translationX)   
public void setTranslationY(float translationY)


//缩放:scaleX、scaleY
public void setScaleX(float scaleX)
public void setScaleY(float scaleY)


2、自定义控件






  • public class MyPointView extends View {  
  •     private Point mPoint = new Point(100);  
  •   
  •     public MyPointView(Context context, AttributeSet attrs) {  
  •         super(context, attrs);  
  •     }  
  •   
  •     @Override  
  •     protected void onDraw(Canvas canvas) {  
  •         if (mPoint != null){  
  •             Paint paint = new Paint();  
  •             paint.setAntiAlias(true);  
  •             paint.setColor(Color.RED);  
  •             paint.setStyle(Paint.Style.FILL);  
  •             canvas.drawCircle(300,300,mPoint.getRadius(),paint);  
  •         }  
  •         super.onDraw(canvas);  
  •     }  
  •   
  •     void setPointRadius(int radius){  
  •         mPoint.setRadius(radius);  
  •         invalidate();  
  •     }  
  •      //初始值  
  •      public int getPointRadius(){  
  •           return 20;  
  •      }  
  •   
  • }   

public class MyPointView extends View {    private Point mPoint = new Point(100);    public MyPointView(Context context, AttributeSet attrs) {        super(context, attrs);    }    @Override    protected void onDraw(Canvas canvas) {        if (mPoint != null){            Paint paint = new Paint();            paint.setAntiAlias(true);            paint.setColor(Color.RED);            paint.setStyle(Paint.Style.FILL);            canvas.drawCircle(300,300,mPoint.getRadius(),paint);        }        super.onDraw(canvas);    }    void setPointRadius(int radius){        mPoint.setRadius(radius);        invalidate();    }     //初始值     public int getPointRadius(){          return 20;     }}



  • private void doPointViewAnimation(){  
  •     ObjectAnimator animator = ObjectAnimator.ofInt(mPointView, "pointRadius", 0, 300, 100);  
  •     animator.setDuration(2000);  
  •     animator.start();  
  • }   

private void doPointViewAnimation(){    ObjectAnimator animator = ObjectAnimator.ofInt(mPointView, "pointRadius", 0, 300, 100);    animator.setDuration(2000);    animator.start();} 四、PropertyValuesHolder
1、保存动画过程所需操作的属性和对应的值。
ofFloat内部实现是将传入的参数封装为PropertyValuesHolder 。




  • public static ObjectAnimator ofFloat(Object target, String propertyName, float... values) {  
  •     ObjectAnimator anim = new ObjectAnimator(target, propertyName);  
  •     anim.setFloatValues(values);  
  •     return anim;  
  • }  

public static ObjectAnimator ofFloat(Object target, String propertyName, float... values) {    ObjectAnimator anim = new ObjectAnimator(target, propertyName);    anim.setFloatValues(values);    return anim;}



  • @Override  
  • public void setFloatValues(float... values) {  
  •     if (mValues == null || mValues.length == 0) {  
  •         // No values yet - this animator is being constructed piecemeal. Init the values with  
  •         // whatever the current propertyName is  
  •         if (mProperty != null) {  
  •             setValues(PropertyValuesHolder.ofFloat(mProperty, values));  
  •         } else {  
  •             setValues(PropertyValuesHolder.ofFloat(mPropertyName, values));  
  •         }  
  •     } else {  
  •         super.setFloatValues(values);  
  •     }  
  • }  

@Overridepublic void setFloatValues(float... values) {    if (mValues == null || mValues.length == 0) {        // No values yet - this animator is being constructed piecemeal. Init the values with        // whatever the current propertyName is        if (mProperty != null) {            setValues(PropertyValuesHolder.ofFloat(mProperty, values));        } else {            setValues(PropertyValuesHolder.ofFloat(mPropertyName, values));        }    } else {        super.setFloatValues(values);    }}



  • public void setValues(PropertyValuesHolder... values) {  
  •     int numValues = values.length;  
  •     mValues = values;  
  •     mValuesMap = new HashMap<String, PropertyValuesHolder>(numValues);  
  •     for (int i = 0; i < numValues;   i) {  
  •         PropertyValuesHolder valuesHolder = values;  
  •         mValuesMap.put(valuesHolder.getPropertyName(), valuesHolder);  
  •     }  
  •     // New property/values/target should cause re-initialization prior to starting  
  •     mInitialized = false;  
  • }  

public void setValues(PropertyValuesHolder... values) {    int numValues = values.length;    mValues = values;    mValuesMap = new HashMap<String, PropertyValuesHolder>(numValues);    for (int i = 0; i < numValues;   i) {        PropertyValuesHolder valuesHolder = values;        mValuesMap.put(valuesHolder.getPropertyName(), valuesHolder);    }    // New property/values/target should cause re-initialization prior to starting    mInitialized = false;}2、构造PropertyValuesHolder:




  • public static PropertyValuesHolder ofFloat(String propertyName, float... values)  
  • public static PropertyValuesHolder ofInt(String propertyName, int... values)  
  • public static PropertyValuesHolder ofObject(String propertyName, TypeEvaluator evaluator, Object... values)  
  • public static PropertyValuesHolder ofKeyframe(String propertyName, Keyframe... values)  

public static PropertyValuesHolder ofFloat(String propertyName, float... values)public static PropertyValuesHolder ofInt(String propertyName, int... values)public static PropertyValuesHolder ofObject(String propertyName, TypeEvaluator evaluator, Object... values)public static PropertyValuesHolder ofKeyframe(String propertyName, Keyframe... values)propertyName: 需要操作的参数名
values : 属性对应可变参数
evaluator:估值器
3、返回ObjectAnimator对象




  • ObjectAnimator.ofPropertyValuesHolder(Object target,PropertyValuesHolder... values)  

ObjectAnimator.ofPropertyValuesHolder(Object target,PropertyValuesHolder... values)target: 需要执行动画的控件
values : 可以是多个PropertyValuesHolder,每一个PropertyValuesHolder对一个属性做动画,多个实例可对控件多个属性动画。




  • PropertyValuesHolder rotationHolder = PropertyValuesHolder.ofFloat("Rotation", 60f, -60f, 40f, -40f, -20f, 20f, 10f, -10f, 0f);  
  • PropertyValuesHolder colorHolder = PropertyValuesHolder.ofInt("BackgroundColor", 0xffffffff, 0xffff00ff, 0xffffff00, 0xffffffff);  
  • ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(mTextView, rotationHolder, colorHolder);  
  • animator.setDuration(3000);  
  • animator.setInterpolator(new AccelerateInterpolator());  
  • animator.start();  

PropertyValuesHolder rotationHolder = PropertyValuesHolder.ofFloat("Rotation", 60f, -60f, 40f, -40f, -20f, 20f, 10f, -10f, 0f);PropertyValuesHolder colorHolder = PropertyValuesHolder.ofInt("BackgroundColor", 0xffffffff, 0xffff00ff, 0xffffff00, 0xffffffff);ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(mTextView, rotationHolder, colorHolder);animator.setDuration(3000);animator.setInterpolator(new AccelerateInterpolator());animator.start();类似于动画集合
(3)ofObject:
例:改变TextView textSize属性
注意:改变属性的类型要匹配,控件有set方法(可自己扩展)




  • private void startAnimator() {  
  •     PropertyValuesHolder charHolder = PropertyValuesHolder.ofObject("textSize",new FloatEvaluator(),10f,20f);  
  •     ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(myText, charHolder);  
  •     animator.setDuration(5000);  
  •     animator.setInterpolator(new AccelerateInterpolator());  
  •     animator.start();  
  • }  
  •   
  • class FloatEvaluator implements TypeEvaluator<Float>{  
  •     @Override  
  •     public Float evaluate(float fraction, Float startValue, Float endValue) {  
  •         return fraction * (endValue -startValue);  
  •     }  
  • }  

private void startAnimator() {    PropertyValuesHolder charHolder = PropertyValuesHolder.ofObject("textSize",new FloatEvaluator(),10f,20f);    ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(myText, charHolder);    animator.setDuration(5000);    animator.setInterpolator(new AccelerateInterpolator());    animator.start();}class FloatEvaluator implements TypeEvaluator<Float>{    @Override    public Float evaluate(float fraction, Float startValue, Float endValue) {        return fraction * (endValue -startValue);    }}4、Keyframe: 关键帧,为了控制动画速率




  • /**
  • * ofFloat  
  • */  
  • public static Keyframe ofFloat(float fraction)  
  • public static Keyframe ofFloat(float fraction, float value)  
  • /**
  • * ofInt  
  • */  
  • public static Keyframe ofInt(float fraction)  
  • public static Keyframe ofInt(float fraction, int value)   

/** * ofFloat  */public static Keyframe ofFloat(float fraction)public static Keyframe ofFloat(float fraction, float value)/** * ofInt  */public static Keyframe ofInt(float fraction)public static Keyframe ofInt(float fraction, int value) fraction:当前进度
value:当前位置
例:





  • Keyframe frame0 = Keyframe.ofFloat(0f, 0);  
  • Keyframe frame1 = Keyframe.ofFloat(0.1f, -20f);  
  • Keyframe frame2 = Keyframe.ofFloat(1, 0);  
  • PropertyValuesHolder frameHolder = PropertyValuesHolder.ofKeyframe("rotation",frame0,frame1,frame2);  
  • Animator animator = ObjectAnimator.ofPropertyValuesHolder(mImage,frameHolder);   
  • animator.setDuration(1000);   
  • animator.start();  

Keyframe frame0 = Keyframe.ofFloat(0f, 0);Keyframe frame1 = Keyframe.ofFloat(0.1f, -20f);Keyframe frame2 = Keyframe.ofFloat(1, 0);PropertyValuesHolder frameHolder = PropertyValuesHolder.ofKeyframe("rotation",frame0,frame1,frame2);Animator animator = ObjectAnimator.ofPropertyValuesHolder(mImage,frameHolder); animator.setDuration(1000); animator.start();2)常用函数:




  • /**
  • * 设置fraction参数,即Keyframe所对应的进度  
  • */  
  • public void setFraction(float fraction)  
  • /**
  • * 设置当前Keyframe所对应的值  
  • */  
  • public void setValue(Object value)  
  • /**
  • * 前一个Keyframe到当前Keyframe期间所对应的插值器  
  • */  
  • public void setInterpolator(TimeInterpolator interpolator)   

/** * 设置fraction参数,即Keyframe所对应的进度  */public void setFraction(float fraction)/** * 设置当前Keyframe所对应的值  */public void setValue(Object value)/** * 前一个Keyframe到当前Keyframe期间所对应的插值器  */public void setInterpolator(TimeInterpolator interpolator) 注:

  • 如果去掉第0帧,将以第一个关键帧为起始位置
  • 如果去掉结束帧,将以最后一个关键帧为结束位置
  • 使用Keyframe来构建动画,至少要有两个或两个以上帧

五、AnimatorSet
1、 playSequentially表示所有动画依次播放,playTogether表示所有动画一起开始。




  • public void playSequentially(Animator... items);  
  • public void playSequentially(List<Animator> items);  
  • public void playTogether(Animator... items);  
  • public void playTogether(Collection<Animator> items);  

public void playSequentially(Animator... items);public void playSequentially(List<Animator> items);public void playTogether(Animator... items);public void playTogether(Collection<Animator> items);



  • private void doPlaySequentiallyAnimator(){  
  •     ObjectAnimator tv1BgAnimator = ObjectAnimator.ofInt(mTv1, "BackgroundColor",  0xffff00ff, 0xffffff00, 0xffff00ff);  
  •     ObjectAnimator tv1TranslateY = ObjectAnimator.ofFloat(mTv1, "translationY", 0, 300, 0);  
  •     ObjectAnimator tv2TranslateY = ObjectAnimator.ofFloat(mTv2, "translationY", 0, 400, 0);  
  •   
  •     AnimatorSet animatorSet = new AnimatorSet();  
  •     animatorSet.playSequentially(tv1BgAnimator,tv1TranslateY,tv2TranslateY);  
  •     animatorSet.setDuration(1000);  
  •     animatorSet.start();  
  • }  

private void doPlaySequentiallyAnimator(){    ObjectAnimator tv1BgAnimator = ObjectAnimator.ofInt(mTv1, "BackgroundColor",  0xffff00ff, 0xffffff00, 0xffff00ff);    ObjectAnimator tv1TranslateY = ObjectAnimator.ofFloat(mTv1, "translationY", 0, 300, 0);    ObjectAnimator tv2TranslateY = ObjectAnimator.ofFloat(mTv2, "translationY", 0, 400, 0);    AnimatorSet animatorSet = new AnimatorSet();    animatorSet.playSequentially(tv1BgAnimator,tv1TranslateY,tv2TranslateY);    animatorSet.setDuration(1000);    animatorSet.start();}注:

  • 如果去掉第0帧,将以第一个关键帧为起始位置
  • 如果去掉结束帧,将以最后一个关键帧为结束位置
  • 使用Keyframe来构建动画,至少要有两个或两个以上帧


2、AnimatorSet.Builder




  • //表示要播放哪个动画  
  • public Builder play(Animator anim)  
  • //和前面动画一起执行  
  • public Builder with(Animator anim)  
  • //执行前面的动画后才执行该动画  
  • public Builder before(Animator anim)  
  • //执行先执行这个动画再执行前面动画  
  • public Builder after(Animator anim)  
  • //延迟n毫秒之后执行动画  
  • public Builder after(long delay)  

//表示要播放哪个动画public Builder play(Animator anim)//和前面动画一起执行public Builder with(Animator anim)//执行前面的动画后才执行该动画public Builder before(Animator anim)//执行先执行这个动画再执行前面动画public Builder after(Animator anim)//延迟n毫秒之后执行动画public Builder after(long delay)串行方式执行:




  • ObjectAnimator tv1BgAnimator = ObjectAnimator.ofInt(mTv1, "BackgroundColor",  0xffff00ff, 0xffffff00, 0xffff00ff);  
  • ObjectAnimator tv1TranslateY = ObjectAnimator.ofFloat(mTv1, "translationY", 0, 400, 0);  
  • ObjectAnimator tv2TranslateY = ObjectAnimator.ofFloat(mTv2, "translationY", 0, 400, 0);  
  •   
  • AnimatorSet animatorSet = new AnimatorSet();  
  • animatorSet.play(tv1TranslateY).with(tv2TranslateY).after(tv1BgAnimator);  
  • animatorSet.setDuration(2000);  
  • animatorSet.start();  

ObjectAnimator tv1BgAnimator = ObjectAnimator.ofInt(mTv1, "BackgroundColor",  0xffff00ff, 0xffffff00, 0xffff00ff);ObjectAnimator tv1TranslateY = ObjectAnimator.ofFloat(mTv1, "translationY", 0, 400, 0);ObjectAnimator tv2TranslateY = ObjectAnimator.ofFloat(mTv2, "translationY", 0, 400, 0);AnimatorSet animatorSet = new AnimatorSet();animatorSet.play(tv1TranslateY).with(tv2TranslateY).after(tv1BgAnimator);animatorSet.setDuration(2000);animatorSet.start();3、函数:




  • //设置单次动画时长  
  • public AnimatorSet setDuration(long duration);  
  • //设置加速器  
  • public void setInterpolator(TimeInterpolator interpolator)  
  • //设置ObjectAnimator动画目标控件  
  • public void setTarget(Object target)  
  • //设置延时开始动画时长(只是延长AnimatorSet的开始时间)  
  • public void setStartDelay(long startDelay)  

//设置单次动画时长public AnimatorSet setDuration(long duration);//设置加速器public void setInterpolator(TimeInterpolator interpolator)//设置ObjectAnimator动画目标控件public void setTarget(Object target)//设置延时开始动画时长(只是延长AnimatorSet的开始时间)public void setStartDelay(long startDelay)四、对任意属性做动画(自定义动画):
1、属性动画的原理:
(1)object必须提供该属性的set方法,多次调用set方法,每次传给set的值不一样。
如果没初始值,还需要get方法,因为系统要获取属性的初始值。


(2)对于属性的改变必须通过某种ui的变化体现出来(不然动画无效)
解决方式:
1、给你的对象加上set和get方法(或者用一个类包装原始类,间接提供get和set方法。)




  • public class Animator {  
  •     private Button button;  
  •     private void performAnimate(){  
  •         //按钮点击后执行的动画  
  •         ViewWrapper viewWrapper = new ViewWrapper(button);  
  •         ObjectAnimator.ofInt(viewWrapper,"width",500).setDuration(5000).start();  
  •     }  
  •   
  •     private static class ViewWrapper{  
  •         private View mtagerView;  
  •   
  •         public ViewWrapper(View target){  
  •             mtagerView = target;  
  •         }  
  •   
  •         public int getWidth(){  
  •             return mtagerView.getLayoutParams().width;  
  •         }  
  •         public void setWidth(int width){  
  •             mtagerView.getLayoutParams().width = width;  
  •             mtagerView.requestLayout();  
  •         }  
  •     }  
  • }  

public class Animator {    private Button button;    private void performAnimate(){        //按钮点击后执行的动画        ViewWrapper viewWrapper = new ViewWrapper(button);        ObjectAnimator.ofInt(viewWrapper,"width",500).setDuration(5000).start();    }    private static class ViewWrapper{        private View mtagerView;        public ViewWrapper(View target){            mtagerView = target;        }        public int getWidth(){            return mtagerView.getLayoutParams().width;        }        public void setWidth(int width){            mtagerView.getLayoutParams().width = width;            mtagerView.requestLayout();        }    }}2、采用ValueAnimator,监听动画过程,自己实现属性的改变




  • public void performAnimate(final int start, final int end, final View targetView){  
  •     final ValueAnimator valueAnimator =ValueAnimator.ofInt(1,100);  
  •     valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {  
  •         //整形估值器,估值时使用  
  •         private IntEvaluator intEvaluator = new IntEvaluator();  
  •         @Override  
  •         public void onAnimationUpdate(ValueAnimator animation) {  
  •             //获取动画的进度  
  •             int currValue=(Integer) animation.getAnimatedValue();  
  •             //当前进度占整个动画的比例  
  •             float fraction= animation.getAnimatedFraction();  
  •             //通过比例计算出宽度,然后在设给Button  
  •             targetView.getLayoutParams().width=intEvaluator.evaluate(fraction,start,end);  
  •             targetView.requestLayout();  
  •         }  
  •     });  
  •     valueAnimator.setDuration(5000).start(); //5000ms内1-100  
  • }  

public void performAnimate(final int start, final int end, final View targetView){    final ValueAnimator valueAnimator =ValueAnimator.ofInt(1,100);    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {        //整形估值器,估值时使用        private IntEvaluator intEvaluator = new IntEvaluator();        @Override        public void onAnimationUpdate(ValueAnimator animation) {            //获取动画的进度            int currValue=(Integer) animation.getAnimatedValue();            //当前进度占整个动画的比例            float fraction= animation.getAnimatedFraction();            //通过比例计算出宽度,然后在设给Button            targetView.getLayoutParams().width=intEvaluator.evaluate(fraction,start,end);            targetView.requestLayout();        }    });    valueAnimator.setDuration(5000).start(); //5000ms内1-100}3、使用动画注意事项

  • OOM:数量较多并图片较大
  • 内存泄露:无限循环动画,需要在Activity中退出时停止
  • 兼容性问题
  • View动画完成,View无法隐藏。需要调用clearAnimation清除View动画
  • 尽量使用dp
  • 动画过程,开启硬件加速

  继续阅读全文



想在安卓巴士找到更多优质博文,可移步博客区

如果对本篇文章感兴趣,请前往,
原文地址:
http://www.apkbus.com/blog-847095-77492.html

3

主题

24

帖子

228

安币

攻城狮

Rank: 3Rank: 3

发表于 2018-4-16 14:09:06 | 显示全部楼层
谢谢分享
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

站长推荐

通过邮件订阅最新安卓weekly信息
上一条 /4 下一条

下载安卓巴士客户端

全国最大的安卓开发者社区

广告投放| 下载客户端|申请友链|手机版|站点统计|安卓巴士 ( 粤ICP备15117877号 )

快速回复 返回顶部 返回列表