Android动画深入分析

          动画分为三种:帧动画,属性动画,视图动画,其实帧动画也属于视图动画的一种,只不过它和平移、旋转等常见的View动画表现形式上略有不同。帧动画是顺序播放一组预先定义好的图片,类似于电影播放,使用xml定义,使用起来比较简单,可以理解为图片的切换动画,很显然,如果图片过大就会导致OOM。视图动画通过对场景里的对象不断做图像转换(平移,缩放,旋转,透明度)从而产生动画效果,它是一种渐进式动画并且View动画支持自定义。它有一个缺点:当执行了图形转换之后,View的事件响应不是在现有的位置,而是在原位置,并且不支持在动画进行中进行回调。属性动画是google在API 11以后推出的新的动画方式,我们一般使用nineoldandroids兼容库去实现对低版本动画的兼容。属性动画解决了视图动画的不足。由于我们的动画牵涉到宽度、高度的变化,并且变化以后还要能响应事件,所以都是使用属性动画来实现。属性动画使用起来也非常简单,可以参考下面实现的两个方法自己去设置动画参数;

一 视图动画

    View动画的作用对象是View,它支持4种动画效果,分别是平移动画、缩放动画、旋转动画、和透明动画。另外帧动画也属于View动画,但是帧动画的表现形式和上面的四种不太一样。

View动画变换效果对应这Animation的4个子类:TranslateAnimation、ScaleAnimation、RotateAnimation和AlphaAnimation。四种动画既可以通过XML来定义,也可以通过代码来创建,对于View动画来说,建议通过XML来定义,因为可读性更好。

View动画的xml定于语法固定,举个栗子:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:shareInterpolator="false">
    <!-- 动画效果  从看不见到可以看见,也就是0到1,变幻时间为5000毫秒-->
    <scale
        android:duration="100"
        android:fromXScale="0.95"
        android:fromYScale="0.95"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toXScale="1.0"
        android:toYScale="1.0" />

    <alpha
        android:duration="100"
        android:fromAlpha="0"
        android:toAlpha="1" />
 
<translate
    android:duration="300"
    android:fillAfter="true"
    android:fromYDelta="0"
    android:interpolator="@android:anim/accelerate_interpolator"
    android:toYDelta="-100%" />
<rotate
    android:fromDegrees="float"
    android:toDegrees="float"
    android:pivotX="float"
    android:pivotY="float"
    />
</set>

Animationan = AnimationUtils.loadAnimation(getContext(), R.anim.auto_left_in);

left_panel.startAnimation(an);

 

除了在XML中定义,也可以通过代码来创建动画。

AlphaAnimation alphaAnimation=new AlphaAnimation(0,1);
alphaAnimation.setDuration(300);
view.startAnimation(alphaAnimation);
 
 
View动画的特殊使用场景
1.   LayoutAnimation
LayoutAnimation作用于ViewGroup,为ViewGroup指定一个动画,这样,当它的子元素出场时就会具有这种动画效果。这种效果是常被用在ListView上,这就可以实现Listview的每个item都已一定的动画形式出现。
举个栗子:
<layoutAnimation
xmlns:android="http://schemas.android.com/apk/res/android"
android:delay="0.5"
android:nimationOrder="normal"
android:animation="@anim/anim_item"/>
 
2.   Activity的切换效果
Activity有默认的切换效果,但是这个效果我们是可以自定义的,主要用到overridePendingTransition(int enterAnim,int exitAnim)这个方法,这个方法必须在startActivity(Intent)或者finish()之后调用才能生效。
 

二 帧动画


     帧动画是顺序播放一组预先定义好的图片,类似于电影播放,系统提供了AnimaitonDrable来使用帧动画
XML:
<animation-list  xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false">
    <item android:drawable="" android:duration="500"/>
    <item android:drawable="" android:duration="500"/>
    <item android:drawable="" android:duration="500"/>
</animation-list>
 
mButton.setBackgroundResource(R.drawable.test);
AnimationDrawable drawable=(AnimationDrawable)mButton.getBackground();
drawable.start();
 

三 属性动画


     属性动画是API 11之后新加入的特性,和View动画不同,它对作用对象进行了扩展,属性动画可以对任何对象做动画。除了作用对象进行扩展以外,属性动画也得到了加强,不再像View动画那样只能支持四种简单的变换。属性动画中有ValueAnimatior,ObjectAnimator和AnimatorSet等概念。
属性动画几乎是无所不能的,只要对象有这个属性,它都能实现动画效果。为了兼容API11以下版本,我们通常用nineoldandroids来兼容低级版本。
1.   改变对象的translationY属性,让其沿着Y轴向上移动一段距离。
ObjectAnimator.ofFloat(target, "translationY", 500).setDuration(325).start();
2.   改变一个对象的背景色属性,典型的情况是改变一个View的背景色。
ValueAnimator transAnim = ObjectAnimator.ofFloat(view, "backgroundColor","0Xffff8080","0Xff8080ff");
transAnim.setDuration(325);
transAnim.setInterpolator(new LinearOutSlowInInterpolator());
transAnim.setEvaluator(new ArgbEvaluator());
transAnim.start();
 
3.动画集合
AnimatorSet set = new AnimatorSet();
set.playTogether(
        ObjectAnimator.ofFloat(view, "ScaleX", 1, 0.92f),
        ObjectAnimator.ofFloat(view, "ScaleY", 1, 0.92f),
        ObjectAnimator.ofFloat(view, "alpha", 1, 0)
);

set.setInterpolator(new FastOutLinearInInterpolator());
set.setDuration(175).start();
 
属性动画也可以动过xml来定义:
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- Before rotating, immediately set the alpha to 0. -->
    <objectAnimator
        android:valueFrom="1.0"
        android:valueTo="0.0"
        android:propertyName="alpha"
        android:duration="0" />

    <!-- Rotate. -->
    <objectAnimator
        android:valueFrom="180"
        android:valueTo="0"
        android:propertyName="rotationY"
        android:interpolator="@android:interpolator/accelerate_decelerate"
        android:duration="@integer/card_flip_time_full" />

    <!-- Half-way through the rotation (see startOffset), set the alpha to 1. -->
    <objectAnimator
        android:valueFrom="0.0"
        android:valueTo="1.0"
        android:propertyName="alpha"
        android:startOffset="@integer/card_flip_time_half"
        android:duration="1" />
</set>
 
AnimatorSet set=(AnimatorSet) AnimatorInflater.loadAnimator(context,R.anim.test);
set.setTarget(view);
set.start();
 

4. 插值器(TimeInterpolator)与估值器(TypeEvaluator)

插值器:根据时间的流逝的百分比来计算出当前属性值改变的百分比。系统预定义的有几种插值器 (LinearOutSlowInInterpolator
FastOutLinearInInterpolatorFastOutSlowInInterpolatorLookupTableInterpolatorPathInterpolatorCompat

满足日常使用要求,若有特殊要求,也可以重写插值器的实现方法,比较简单;

package android.support.v4.view.animation;


public class FastOutSlowInInterpolator extends LookupTableInterpolator {

    /**
     * Lookup table values sampled with x at regular intervals between 0 and 1 for a total of
     * 201 points.
     */
    private static final float[] VALUES = new float[] {
            0.0000f, 0.0001f, 0.0002f, 0.0005f, 0.0009f, 0.0014f, 0.0020f,
            0.0027f, 0.0036f, 0.0046f, 0.0058f, 0.0071f, 0.0085f, 0.0101f,
            0.0118f, 0.0137f, 0.0158f, 0.0180f, 0.0205f, 0.0231f, 0.0259f,
            0.0289f, 0.0321f, 0.0355f, 0.0391f, 0.0430f, 0.0471f, 0.0514f,
            0.0560f, 0.0608f, 0.0660f, 0.0714f, 0.0771f, 0.0830f, 0.0893f,
            0.0959f, 0.1029f, 0.1101f, 0.1177f, 0.1257f, 0.1339f, 0.1426f,
            0.1516f, 0.1610f, 0.1707f, 0.1808f, 0.1913f, 0.2021f, 0.2133f,
            0.2248f, 0.2366f, 0.2487f, 0.2611f, 0.2738f, 0.2867f, 0.2998f,
            0.3131f, 0.3265f, 0.3400f, 0.3536f, 0.3673f, 0.3810f, 0.3946f,
            0.4082f, 0.4217f, 0.4352f, 0.4485f, 0.4616f, 0.4746f, 0.4874f,
            0.5000f, 0.5124f, 0.5246f, 0.5365f, 0.5482f, 0.5597f, 0.5710f,
            0.5820f, 0.5928f, 0.6033f, 0.6136f, 0.6237f, 0.6335f, 0.6431f,
            0.6525f, 0.6616f, 0.6706f, 0.6793f, 0.6878f, 0.6961f, 0.7043f,
            0.7122f, 0.7199f, 0.7275f, 0.7349f, 0.7421f, 0.7491f, 0.7559f,
            0.7626f, 0.7692f, 0.7756f, 0.7818f, 0.7879f, 0.7938f, 0.7996f,
            0.8053f, 0.8108f, 0.8162f, 0.8215f, 0.8266f, 0.8317f, 0.8366f,
            0.8414f, 0.8461f, 0.8507f, 0.8551f, 0.8595f, 0.8638f, 0.8679f,
            0.8720f, 0.8760f, 0.8798f, 0.8836f, 0.8873f, 0.8909f, 0.8945f,
            0.8979f, 0.9013f, 0.9046f, 0.9078f, 0.9109f, 0.9139f, 0.9169f,
            0.9198f, 0.9227f, 0.9254f, 0.9281f, 0.9307f, 0.9333f, 0.9358f,
            0.9382f, 0.9406f, 0.9429f, 0.9452f, 0.9474f, 0.9495f, 0.9516f,
            0.9536f, 0.9556f, 0.9575f, 0.9594f, 0.9612f, 0.9629f, 0.9646f,
            0.9663f, 0.9679f, 0.9695f, 0.9710f, 0.9725f, 0.9739f, 0.9753f,
            0.9766f, 0.9779f, 0.9791f, 0.9803f, 0.9815f, 0.9826f, 0.9837f,
            0.9848f, 0.9858f, 0.9867f, 0.9877f, 0.9885f, 0.9894f, 0.9902f,
            0.9910f, 0.9917f, 0.9924f, 0.9931f, 0.9937f, 0.9944f, 0.9949f,
            0.9955f, 0.9960f, 0.9964f, 0.9969f, 0.9973f, 0.9977f, 0.9980f,
            0.9984f, 0.9986f, 0.9989f, 0.9991f, 0.9993f, 0.9995f, 0.9997f,
            0.9998f, 0.9999f, 0.9999f, 1.0000f, 1.0000f
    };

    public FastOutSlowInInterpolator() {
        super(VALUES);
    }

}

估值器:类型估值算法,根据当前属性改变的百分比来计算改变后的属性值,系统预设置的有IntEvaluator,FloatEvaluator,ArgbEvaluator。估值器和插值器是实现非迅速动画的重要手段。

 

5. 属性动画监听器

a)   属性动画提供了监听器用于监听动画的播放过程,主要有如下两个接口:AnimatorUpdateListener和AnimatorListerer。
AnimatorListerer定义如下:

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

b)   AnimatorUpdateListener定于如下:

public static interface AnimatorUpdateListener {

    void onAnimationUpdate(ValueAnimator animation);

}

6.  对任意属性做动画

     举个栗子:

对一个Button的宽度进行变化,按下面这样写,是否正确?

ObjectAnimator.ofFloat(target, "width", 500).setDuration(325).start();

 

答案是否定的。因为Button没有setWidth方法来改变其宽度,Button继承自TextView,而TextView的setWidth方法不是用来设置TextView的宽度的,而是设置其最大宽度与最小宽度。具体来说android:layout_width对应textView的width属性,而不是android:width。总之,通过这个方法,无法改变TextView的宽度。官方文档给出了3种解法:

1.  改你的对象加上get和set方法,如果你权限的话。

2.  用一个类来包装原始对象,间接为期提供get与set方法;

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

对于2,举个栗子:

ViewWrapperwrapper=new ViewWrapper(target);

ObjectAnimator.ofFloat(wrapper, "width", 500).setDuration(325).start();

 

private static class ViewWrapper {
    private View mTarget;

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

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

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

对于3,举个栗子:

ValueAnimator transAnim = ObjectAnimator.ofInt(1, 100);
transAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    private IntEvaluator mEvaluator = new IntEvaluator();

    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        //获取当前动画进度值,整型,1~100
        int currentValue = (Integer) animation.getAnimatedValue();
        float fraction = animation.getAnimatedFraction();
        target.getLayoutParams().width = mEvaluator.evaluate(fraction, start, end);
        target.requestLayout();
    }
});
transAnim.setDuration(325);
transAnim.setInterpolator(new LinearOutSlowInInterpolator());
transAnim.start();

 

 

累死了,今天就写这么多。


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值