Android Animation

1、Android Animation设计模式
Android的架构中用了很多的设计模式,Android的动画模型感触颇深,笔者之前开发过C++的动画模型,动画的模型和具体的元素耦合在一起,代码混乱,难以维护,使用复杂度高,可复用性低。
android 动画结构
动画自成体系,和view通过接口交互,既具备模块隔离性,又保证了充分的扩展性。
至于实现view动画的细节实现,有机会还需要仔细研究下,刚入手重点还放在应用层面。
2、Android动画
Android动画整体可范围三类:view animation,drawable animation,property animation
2.1 view animation
View Animation只能应用于view对象,并且要注意的一点,对于View Animation,它只是改变了View对象绘制的位置,并没有改变View对象本身。比如,你定义了一个View,属性为(x:100,y:100,width:100,height:100),有一个动画使其变为(x:100,y:100,width:50,width:50),在动画过程中Button的点击区域仍然是(x:100,y:100)->(200,200).
View Animation支持支持四种动画效果,TranslateAnimation,ScaleAnimation,RotateAnimation,AlphaAnimation。动画的定义既可以通过XML方式来定义,也可以通过动态代码方式来创建。
单个View可以同时设置多个动画,默认多个动画是同时进行的,可以通过startOffset属性设置各个动画的开始偏移(开始时间)来达到动画顺序播放的效果。
通过XML方式定义View动画,需要在res/anim文件夹内创建xml文件,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/linear_interpolator"
    android:duration="150"
    android:fromDegrees="0.0"
    android:toDegrees="-225.0"
    android:pivotX="50.0%"
    android:pivotY="50.0%"
    android:fillAfter="true"
    android:fillEnabled="true">

</rotate>

在代码中,加载XML文件实例化Animation,指定给指定的View即可。

Button mButton = (Button)findViewById(R.id.button1);
Animation animation = AnimationUtils.loadAnimation(this,
                R.anim.rotate_button_in);
mButton.startAnimation(animation);

XML文件的根元素可以为:,,,,(表示以上几个动画的集合,set可以嵌套,默认set内动画元素同时执行)

还可以通过代码方式定义动画

Button mButton = (Button)findViewById(R.id.button1);
AlphaAnimation alphaAnimation = new AlphaAnimation(0,1);
alphaAnimation.setDuration(200);
mButton.startAnimation(alphaAnimation);

2.2 Drawable Animation
Drawable Animation通过顺序播放一组图片来实现动画的效果,使用方法如下:
在res/drawable/目录下新建Drawable

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item android:drawable="@drawable/image1" android:duration="500" />
<item android:drawable="@drawable/image2" android:duration="500" />
<item android:drawable="@drawable/image3" android:duration="500" />
</animation-list >

调用逻辑如下:

Button mButton = (Button)findViewById(R.id.button1);
mButton.setBackgroundResource(R.drawable.frame_animation);
AnimationDrawable drawable = (AnimationDrawable)mButton.getBackground();
drawable.start();

2.3 属性动画
属性动画是API 11后引入的,它扩展了动画的作用对象,可以对任何对象做动画,同时扩展了动画效果,可以实现更为绚丽的效果。属性动画几乎无所不能,只有对象有这个属性,就可以针对它做动画。在API 11版本之前,可以采用开源动画库nineoldandroids兼容以前版本。
2.3.1 属性动画的基础用法
属性动画中比较常用的几个类:ValueAnimator、ObjectAnimator、AnimatorSet。
与View动画一样,属性动画也有两种创建方法:通过代码创建和通过XML创建。
1)实现button上下平移的动画。

Button aniBtn = (Button)findViewById(R.id.btn_anim);
        ValueAnimator alphaAnim = ObjectAnimator.ofFloat(aniBtn, "translationY", 0,90);
        alphaAnim.setDuration(5000);
        alphaAnim.setRepeatCount(ValueAnimator.INFINITE);
        alphaAnim.start();

2) 改变View的背景色,实现在3s内从0xFFFF8080到0xFF8080FF的渐变,动画会无限重复。

ValueAnimator colorAnim = ObjectAnimator.ofInt(customView, "backgroundColor",0xFFFF8080,0xFF8080FF);
colorAnim.setDuration(3000);
colorAnim.setEvaluator(new ArgbEvaluator());
colorAnim.setRepeatCount(ValueAnimator.INFINITE);
colorAnim.start();

3) 动画集合,5s内对View的旋转、平移、缩放和透明度都进行改变。

AnimatorSet set = new AnimatorSet();
set.playTogether(
    ObjectAnimator.ofFloat(customView, "rotationX", 0, 360);
    ObjectAnimator.ofFloat(customView, "rotationY", 0, 180);
    ObjectAnimator.ofFloat(customView, "translationX", 0, 90);
    ObjectAnimator.ofFloat(customView, "translationY", 0, 90);
    ObjectAnimator.ofFloat(customView, "scaleX", 1, 1.5f);
    ObjectAnimator.ofFloat(customView, "scaleY", 1, 0.5f);
    ObjectAnimator.ofFloat(customView, "alpha", 1, 0.25f,1);

);
set.setDuration(5000).start();

通过XML创建

属性动画需要定义在res/animator/目录下,格式如下:

<set android:ordering=["together"|"sequentially"]>
<objectAnimator 
    android:propertyName="string"
    android:duration="int"
    android:valueFrom="float|int|color"
    android:valueTo="float|int|color"
    android:startOffset="int"
    android:repeatCount="int"
    android:repeatMode=["repeat|reverse"]
    android:valueType=["intType|floatType"]/>

<Animator 
    android:duration="int"
    android:valueFrom="float|int|color"
    android:valueTo="float|int|color"
    android:startOffset="int"
    android:repeatCount="int"
    android:repeatMode=["repeat|reverse"]
    android:valueType=["intType|floatType"]/>

<set>
    ...
</set>
</set>

使用属性动画的方式也很简单

AnimatorSet set=(AnimatorSet)AnimatorInflater.loadAnimator(customContext,R.anim.property_animator);
set.setTarget(mButton);
set.start();

2.3.2 属性动画的扩展
属性动画的Interpolator和TypeEvaluator很重要,通过自定义这两个接口可以实现千奇百怪的动画效果。
LinearInterpolator的源码:

public class LinearInterpolator implements Interpolator{

    public LinearInterpolator(){
    }

    public LinearInterpolator(Context context, AttributeSet attrs)(){
    }

    public float getInterpolation(float input){
    return input;
    }
}

IntEvaluator的源码

public class IntEvaluator implements TypeEvaluator<Integer>{
    public Integer evaluate(float fraction, Integer startValue, Integer endValue){
        int startInt = startValue;
        return (int)(startInt + fraction*(endValue-startValue))
    }
}

属性动画还提供了AnimatorUpdateListener和AnimatorListener两个监听器,用来监听动画的播放过程。
AnimatorLister的定义如下:

public static interface AnimatorLister{
    void onAnimationStart(Animator animation);
    void onAnimationEnd(Animator animation);
    void onAnimationCancel(Animator animation);
    void onAnimationRepeat(Animator animation);
}

AnimatorUpdateListener的定义如下:

public static interface AnimatorUpdateListener{
    void onAnimationUpdate(ValueAnimator animation);
}

2.3.3 对任意属性做动画
针对Object属性abc的属性动画要生效,必须同时满足两个条件:
1) Object必须要提供setAbc的方法,如果动画的时候没有传递初始值,还必须提供getAbc的方法,因为系统要去取Abc属性的初始值(该条不满足,程序直接crash)
2)Object的setAbc方法对属性abc的改变必须能够通过某种方式反映出来,比如会带来UI改变之类的(不满足这条,动画无效果但不会crash)
如何给对象属性添加set和get方法,官方文档提供三个解决方法:
1、如果有权限的话,给你的对象加上get和set方法;
简单有效,但往往我们没有权限。
2、用一个类包装原始对象,间接为其提供get和set方法;

private void performAnimate(){
    ViewWrapper wrapper = new ViewWrapper(mButton);
    ObjectAnimator.ofInt(wrapper,"width",500).setDuration(5000).start();
}

@override
public void onClick(View v){
    if (v == mButton){
        performAnimate();
    }
}

private static class ViewWrapper {
    private View mTarget;

    public ViewWrapper(View target){
        mTarget = target;
    }

    public int getWidth(){
        return mTarget.getLayoutParam().width;
    }

    public void setWidth(int width){
        mTarget.getLayoutParam().width = width;
        mTarget.requestLayout();
    }

}

3、采用ValueAnimator, 监听动画过程,自己实现属性的改变。

private void performAnimate(final View target, final int start, final int end){
    ValueAnimator valueAnimator = ValueAnimator.ofInt(1,100);
    valueAnimator.addUpdateListener(new AnimatorUpdateListener(){
    private IntEvaluator mEvaluator = new IntEvaluator();

    @override
    public void onAnimationUpdate(ValueAnimator animator){
        int currentValue = (Interge)animator.getAnimateValue();

        float fraction = animator.getAnimateFraction();

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

参考资料:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值