深入学习属性动画

深入学习属性动画

1.动画三种方式

动画名称 动画的定义
逐帧动画 将一张完整的图片拆成一张张图片单独的播放
补间动画 可以对view进行一些列的动画操作
属性动画 可以对非view的对象就行动画操作,可以改变view的属性而不单单是改变view的动画效果

2.属性动画的学习

1.ValueAnimator

ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);  
anim.setDuration(300);  
anim.start();                                                               

valueAnimatior会自动的从初始值,过度到结束值这样的效果,还负责管理动画的播放次数。
播放模式。

监听动画的执行:

ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);  
anim.setDuration(300);          
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {  
@Override  
public void onAnimationUpdate(ValueAnimator animation) {  
    float currentValue = (float) animation.getAnimatedValue();  
    Log.d("TAG", "cuurent value is " + currentValue);  
}  
});  
anim.start();                                                  

2.ObjectAnimator

ValueAnimator知不是对值的平滑的动画过渡而ObjectAnimator可以直接对任意对象任意属性进行
动画操作。ObjectAnimatior继承自ValueAnimator用法类似,将一个TextView在五秒内从常规变成透明再变成常规:

ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "alpha", 1f, 0f, 1f);  
animator.setDuration(5000);  
animator.start(); 

3.组合动画

实现组合动画主要用到AnimatorSet类,这个类提供了一个play()的方法,返回一个AnimatorSet实例
AnimatorSet.Builder中包括四个方法

  • after(Animator anim),将现有动画插入到传入的动画之后

  • after(long delay),将现有动画延迟到制定动画之后

  • before(Animator anim),将现有动画插入到传入的动画之前

  • with(Animator anim),将现有动画和传入的动画同时执行。

    ObjectAnimator moveIn = ObjectAnimator.ofFloat(textview, "translationX", -500f, 0f);  
    ObjectAnimator rotate = ObjectAnimator.ofFloat(textview, "rotation", 0f, 360f);  
    ObjectAnimator fadeInOut = ObjectAnimator.ofFloat(textview, "alpha", 1f, 0f, 1f);  
    AnimatorSet animSet = new AnimatorSet();  
    animSet.play(rotate).with(fadeInOut).after(moveIn);  
    animSet.setDuration(5000);  
    animSet.start(); 
    

4.Animator监听器

监听动画何时开始,何时结束,Animator类提供了一个addListener()方法,这个方法接受一个AnimatorListener。添加一个监听器的示例代码:

anim.addListener(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,解决。示例代码:

anim.addListener(new AnimatorListenerAdapter() {  
@Override  
public void onAnimationEnd(Animator animation) {  
}  
});  

5.使用XML编写动画

如果使用XML来编写动画,需要在res目录下创建一个animator文件,在XML文件中添加三种标签

  • <animator> 标签对应代码中的ValueAnimator:实现一个而从0到100的平滑过渡

    <animator xmlns:android="http://schemas.android.com/apk/res/android"  
    android:valueFrom="0"  
    android:valueTo="100"  
    android:valueType="intType"/>  
    
  • <objectAnimator>对应代码的ObjectAnimator;实现透明度从1到0的动画

    <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"  
    android:valueFrom="1"  
    android:valueTo="0"  
    android:valueType="floatType"  
    android:propertyName="alpha"/>  
    
  • <set>对应代码的AnimatorSet

    Xml文件编写之后在代码中的加载方式:

    Animator animator = AnimatorInflater.loadAnimator(context, R.animator.anim_file);  
    animator.setTarget(view);  
    animator.start(); 
    

ValueAnimator的高级用法

在自定义一个View的时候,在这个View中有Point对象管理座标,然后在onDraw()方法中就是根据这个Point对象的座标值,进行绘制,如果我们对整个自定义View的动画效果就有了。

先了解TypeEvaluator的用法:简单来说就是告诉动画系统,如何从初始值过渡到结束值。比如ValueAnimator.ofFloat()就是实现了从初始值到结束值的平滑过渡,其实就是系统内置了一个FloatEvaluator:代码实现如下,

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);  
    }  
}  

三个参数的意义:

  • fraction,表示动画的完成度。

  • startValue 动画的初始值

  • endValue 动画的结束值

ObjectAnimator的高级用法

补间动画只能实现移动,缩放等操作,但是要对view的颜色进行动态改变就无法实现。

ObjectAnimator:内部的工作机制是通过寻找特定的属性的get和set方法,然后通过对值不断的改变从而实现动画。比如,我们自定义一个View,只需要在其内部这样写:

 public class MyAnimView extends View {  
 ...  
 private String color;  
 public String getColor() {  
        return color;  
 }  
  public void setColor(String color) {  
        this.color = color;  
        mPaint.setColor(Color.parseColor(color));  
        invalidate();  
    }  
    ...  
}   

Interpolator的用法

Interpolator:直译是补间器的意思。它的主要作用是可以控制动画的变化速率,比如去实现一种非线性运动的动画效果。那么什么叫做非线性运动的动画效果呢?就是说动画改变的速率不是一成不变的,像加速运动以及减速运动都属于非线性运动。不过Interpolator并不是属性动画中新增的技术,实际上从Android 1.0版本开始就一直存在Interpolator接口了,而之前的补间动画当然也是支持这个功能的。只不过在属性动画中新增了一个TimeInterpolator接口,这个接口是用于兼容之前的Interpolator的,这使得所有过去的Interpolator实现类都可以直接拿过来放到属性动画当中使用 。

  • AccelerateDecelerateInterpolator 先加速后减速的interpolator,系统默认的补间器。

  • AccelerateInterpolator 加速的补间器

  • DecelerateInterpolator 减速的补间器。

    系统内置的补间器非常多。interpolator的内部实现机制是什么:

    /** 
    * A time interpolator defines the rate of change of an animation. This allows animations 
    * to have non-linear motion, such as acceleration and deceleration. 
    */  
     public interface TimeInterpolator {  
    
    /** 
     * Maps a value representing the elapsed fraction of an animation to a value that represents 
     * the interpolated fraction. This interpolated value is then multiplied by the change in 
     * value of an animation to derive the animated value at the current elapsed animation time. 
     * 
     * @param input A value between 0 and 1.0 indicating our current point 
     *        in the animation where 0 represents the start and 1.0 represents 
     *        the end 
     * @return The interpolation value. This value can be more than 1.0 for 
     *         interpolators which overshoot their targets, or less than 0 for 
     *         interpolators that undershoot their targets. 
     */  
    float getInterpolation(float input);  
     }  
    

    getInterpolation()方法接收了一个input值,这个值随着动画的运行不断变化,不过变化是有规率可寻的,就是根据设定动画时长匀速增加。变化范围是0到1即:动画开始的时候input值为0,动画结束的时候input值为1。inuput值与fraction值之间有什么关系?input值就是fraction。input值经过系统计算,传入到getINnterpolation中,然后我们可以自己实现这个方法,经过计算返回input值,这个值就是fraction参数。因此最简单的就是input值与fraction相同。系统中内置LinearInterpolator就是一种匀速运动的Interpolator,那么我们来看一下它的源码是怎么实现的:

    /** 
     * An interpolator where the rate of change is constant 
     */  
    @HasNativeInterpolator  
    public class LinearInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {  
    public LinearInterpolator() {  
    }  
    public LinearInterpolator(Context context, AttributeSet attrs) {  
    }  
    public float getInterpolation(float input) {  
    return input;  
    }  
    /** @hide */  
    @Override  
     public long createNativeInterpolator() {  
    return NativeInterpolatorFactoryHelper.createLinearInterpolator();  
     }  
    }    
    

    知道补间器里面的实现过程自定义一个先加速,后减速的补间器。

    /**
    * @author [email protected]
    * @Company 杭州木瓜科技有限公司
    * @date 2016/8/3
    */
    public class DefineInterpolation implements TimeInterpolator {
    
     @Override
    public float getInterpolation(float input) {
    if (input<0.5){
        input= (float) ((Math.sin(input*Math.PI)))/2;
    }else {
        input= (float) (2-Math.sin(input*Math.PI))/2;
    }
    return input;
    }
    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章