Android View动画

  • Animation
  • TypeEvaluator
  • View的animate方法
  • ValueAnimator
  • ObjectAnimator
  • AnimatorSet
  • 使用xml来创建动画
    • animation
    • objectAnimator
    • set
    • Animator set
  • 自己定义ObjectAnimator属性
  • propertyValuesHolder
  • Keyframe
  • Interpolator
    • 贝塞尔曲线
    • PathInterpolator
    • 加减速引子


Android的动画模式:tween animation,frame animation和property animation,又叫View Animation,Drawable Animation和Property Animation。前两种是3.0曾经版本号支持的。属性动画是3.0以后支持的。

Animation和Animator的差别:Animation仅仅是view的绘制效果,但实际属性没有改变。而Animator改变的是view的属性。比方做位移动画。用Animation时view的实际位置没有改变,而Animator能够改变view的位置。

本文重点介绍属性动画。

1.Animation

用Animation能够实现AlphaAnimation,ScaleAnimation,TranslateAnimation,RotateAnimation。

比方:

        float fromY = 0f;
        float toY = 100f;
        anim = new TranslateAnimation(0.0f, 0.0f, fromY, toY);
        anim.setInterpolator(new LinearInterpolator());
        anim.setDuration(3000);
        anim.setStartOffset(700);
        anim.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {

            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });
        view.startAnimation(anim);

2. TypeEvaluator

TypeEvaluator提供了一个接口,开发人员能够通过实现该接口自己定义Evaluator。

眼下系统提供的Evaluator有以下几种:

ArgbEvaluator,FloatArrayEvaluator,FloatEvaluator,IntArrayEvaluator。IntEvaluator。RectEvaluator,PointFEvaluator等,

看ArgbEvaluator的实现,我们发现仅仅须要依据我们定义的属性简单的实现evaluate方法就能够了。

这样我们就能够定义自己的XXEvaluator了。

依据动画运行的时间跟应用的Interplator,会计算出一个0~1之间的因子。即evalute函数中的fraction參数。

public class ArgbEvaluator implements TypeEvaluator {
    private static final ArgbEvaluator sInstance = new ArgbEvaluator();

    public static ArgbEvaluator getInstance() {
        return sInstance;
    }

    public Object evaluate(float fraction, Object startValue, Object endValue) {
        int startInt = (Integer) startValue;
        int startA = (startInt >> 24) & 0xff;
        int startR = (startInt >> 16) & 0xff;
        int startG = (startInt >> 8) & 0xff;
        int startB = startInt & 0xff;

        int endInt = (Integer) endValue;
        int endA = (endInt >> 24) & 0xff;
        int endR = (endInt >> 16) & 0xff;
        int endG = (endInt >> 8) & 0xff;
        int endB = endInt & 0xff;

        return (int)((startA + (int)(fraction * (endA - startA))) << 24) |
                (int)((startR + (int)(fraction * (endR - startR))) << 16) |
                (int)((startG + (int)(fraction * (endG - startG))) << 8) |
                (int)((startB + (int)(fraction * (endB - startB))));
    }
}

样例:

        ValueAnimator backgroundColor = ValueAnimator.ofObject(new ArgbEvaluator(),
                0xffffffff, 0xff000000);
        backgroundColor.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animation) {

            }
            @Override
            public void onAnimationEnd(Animator animation) {

            }
        });
        backgroundColor.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int color = (int) animation.getAnimatedValue();
                mView.setBackgroundColor(color);
            }
        });
        backgroundColor.setInterpolator(new LinearInterpolator());
        backgroundColor.setDuration(500);
        backgroundColor.start();

3. View的animate()方法

我们也能够直接使用View的API animate()来做动画,并且还能够几个动画同一时候做哦!

以下的样例就实现了一个View的X位移、透明度、缩放的动画

        view.animate().translationX(animTranslationXPx)
                .alpha(0.5f)
                .setStartDelay(0)
                .scaleX(0.8f)
                .scaleY(0.8f)
                .setUpdateListener(null)
                .setInterpolator(new AccelerateDecelerateInterpolator())
                .setDuration(1000)
                .withEndAction(new Runnable() {
                    @Override
                    public void run() {

                    }
                })
                .start();

4. ValueAnimator

ValueAnimator就是一个数值产生器,他本身不作用于不论什么一个对象。可是能够对产生的值进行动画处理。

为了实现动画效果,必须为ValueAnimator注冊一个监听器ValueAnimator.AnimatorUpdateListener。该监听器负责更新对象的属性值。在实现这个监听器的时候。能够通过getAnimatedValue()的方法来获取当前帧的值。

以下样例用ValueAnimator来实现了一个缩放和位移动画:

        final Rect fromRect = ......
        final Rect toRect = ......

        final float originScaleX = 1.0f;//(float)fromRect.width() / toRect.width();
        final float originScaleY = 1.0f;//(float)fromRect.height() / toRect.height();

        ValueAnimator trans = ValueAnimator.ofFloat(0, 1);
        trans.setInterpolator(new LinearInterpolator());
        trans.setDuration(600);
        trans.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) {

            }
        });
        trans.addUpdateListener(new AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float percent = (Float)animation.getAnimatedValue();

                float toX = (fromRect.left + percent * (toRect.left - fromRect.left));
                float toY = (fromRect.top + percent * (toRect.top - fromRect.top));
                float toR = (fromRect.right + percent * (toRect.right - fromRect.right));
                float toB = (fromRect.bottom + percent * (toRect.bottom - fromRect.bottom));
                float scaleX = (float)(toR - toX) / fromRect.width();
                float scaleY = (float)(toB - toY) / fromRect.height();
                view.setTranslationX(toX-view.getLeft());
                view.setTranslationY(toY-view.getTop());
                view.setScaleX(scaleX*originScaleX);
                view.setScaleY(scaleY*originScaleY);
                float alpha = 0 + percent * 1 / (0.8f - 0);
        ......
            }
        });
        trans.start();

5. ObjectAnimator

ObjectAnimator继承自ValueAnimator,它会自己主动更新我们定义的属性值,来实现动画的目的。

以下的样例是用ObjectAnimator来实现X轴位移的动画:

        ObjectAnimator anim = ObjectAnimator.ofFloat(v,View.TRANSLATION_X, newPos);
        anim.setInterpolator(new LinearInterpolator());
        anim.setDuration(500);
        anim.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {

            }
        });
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {

            }
        });
        anim.start();

6. AnimatorSet

AnimatorSet用于实现多个动画的协同作用,AnimatorSet中有一系列的顺序控制方法:playTogether、playSequentially、animSet.play().with()、defore()、after()等。

用来实现多个动画的协同工作方式。

以下的样例用AnimatorSet实现了缩放和位移动画:

        ObjectAnimator trans = ObjectAnimator.ofFloat(view,View.TRANSLATION_X, newPos);
        ObjectAnimator scalex = ObjectAnimator.ofFloat(view, View.SCALE_X, 1.0f, 0.8f);
        ObjectAnimator scaley = ObjectAnimator.ofFloat(view, View.SCALE_Y, 1.0f, 0.8f);
        AnimatorSet animSet = new AnimatorSet();
        animSet.playTogether(scalex, scaley, trans);
        animSet.setDuration(duration);
        animSet.setInterpolator(new LinearInterpolator());
        animSet.addListener(new AnimatorListener() {

            @Override
            public void onAnimationCancel(Animator animation) {
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                // do end;
            }

            @Override
            public void onAnimationRepeat(Animator animation) {
            }

            @Override
            public void onAnimationStart(Animator animation) {
            }

        });
        animSet.start();

关于时间的设置问题:

假设AnimatorSet设置了setDuration,那么无论子动画有没有设置时间。都要AnimatorSet的时间为准,假设AnimatorSet没有设置。那么子动画以各自的时间为准。当全部动画完毕后调用onAnimationEnd。

7.使用xml来创建动画

animation

        final Animation ani = AnimationUtils.loadAnimation(this, R.anim.test);
        ani.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
            }
            @Override
            public void onAnimationEnd(Animation animation) {
            }
            @Override
            public void onAnimationRepeat(Animation animation) {
            }
        });
        mView.startAnimation(ani);
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:fromXScale="1.0" android:toXScale="0.2"
    android:fromYScale="1.0" android:toYScale="1.0"
    />

当然也能够用以下的方式做。

objectAnimator

        Animator ani= AnimatorInflater.loadAnimator(this, R.anim.test);
        ani.setTarget(mView);
        ani.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
            }
        });
        ani.start();

test.xml

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:propertyName="scaleX"
    android:valueFrom="1.0"
    android:valueTo="0.2"
    android:valueType="floatType" >
</objectAnimator>

注意两个R.anim.test不要用错,否则会报错。

通过这个动画也能够看出一般动画和属性动画的差别:

animation做完动画后属性会恢复原样。也就是说它改变的是View的绘制效果,真正的View的属性并没有改变,animator做完动画后保持动画完毕时的属性不变,说明它把View的属性改变了。

set

R.anim.test

<set xmlns:android="http://schemas.android.com/apk/res/android"
        android:shareInterpolator="false"
        android:zAdjustment="top">
    <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
            android:interpolator="@interpolator/test_alpha"
            android:fillEnabled="true"
            android:fillBefore="false" android:fillAfter="true"
            android:duration="336"/>
    <translate android:fromYDelta="15%" android:toYDelta="0"
            android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
            android:interpolator="@interpolator/test_translate"
            android:duration="336"/>
    <scale android:fromXScale="0.94" android:toXScale="1.0"
            android:fromYScale="0.94" android:toYScale="1.0"
            android:interpolator="@interpolator/test_scale"
            android:duration="336"
            android:pivotX="50%"
            android:pivotY="50%"/>
</set>

R.interpolator.test_alpha

<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" android:controlX1="0.1"
    android:controlY1="0" android:controlX2="0" android:controlY2="1" />

Java

        final Animation ani = AnimationUtils.loadAnimation(mActivity, R.anim.test);
        ani.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
            }
            @Override
            public void onAnimationEnd(Animation animation) {

            }
            @Override
            public void onAnimationRepeat(Animation animation) {
            }
        });
        imageView.startAnimation(ani);

Animator set

当然也能够用以下的方式实现:

test_animator.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:ordering="together"
    android:shareInterpolator="false"
    android:zAdjustment="top">
    <objectAnimator
        android:propertyName="alpha"
        android:valueFrom="0.0"
        android:valueTo="1.0"
        android:valueType="floatType"
        android:interpolator="@interpolator/test_alpha"
        android:duration="336"
        />
    <objectAnimator
        android:propertyName="translationY"
        android:valueFrom="@dimen/translation_y"
        android:valueTo="0"
        android:valueType="floatType"
        android:interpolator="@interpolator/test_alpha"
        android:duration="336"
        />
    <set android:ordering="together">
        <objectAnimator
            android:propertyName="scaleX"
            android:valueFrom="0.94"
            android:valueTo="1.0"
            android:valueType="floatType"
            android:interpolator="@interpolator/test_scale"
            android:duration="336"
            />
        <objectAnimator
            android:propertyName="scaleY"
            android:valueFrom="0.94"
            android:valueTo="1.0"
            android:valueType="floatType"
            android:interpolator="@interpolator/test_scale"
            android:duration="336"
            />
    </set>
</set>

Java

        Animator animator = AnimatorInflater.loadAnimator(mActivity, R.animator.test_animator);
        animator.setTarget(view);
        animator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                end.run();
            }

            @Override
            public void onAnimationCancel(Animator animation) {
                end.run();
            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
        animator.start();

8.自己定义ObjectAnimator属性

通常情况下我们使用ObjectAnimator来实现动画效果,能够用以下的方法:

ObjectAnimator anim = ObjectAnimator.ofFloat(view, "alpha", 0f, 1f);
anim.setDuration(1000);
anim.start();

由于在View中已经实现了alpha属性的动画,那么假设在View中没有实现的属性我们怎样使用ObjectAnimator来做动画呢?

我们能够用以下的方法:

ObjectAnimator anim = ObjectAnimator.ofFloat(myTextView, "test", 0f, 1f);
anim.setDuration(1000);
anim.start();

test就代表了View的一个属性,仅仅须要一个类继承View并实现

public void setTest(float set){
    //to do something
}

假设用以下这样仅仅为该属性设置一个属性值,那么还要实现getter的方法:

ObjectAnimator anim = ObjectAnimator.ofFloat(view, "testt",  1f);
anim.setDuration(1000);
anim.start();

public void setTestt(float set){
    mTestt = set;
}

public float getTestt(){
    return mTestt;
}

当然假设view中没有该属性的动画,那么还能够用ValueAnimator来实现。仅仅只是要ValueAnimator.AnimatorUpdateListener接口。自己更新对应的属性值

9.propertyValuesHolder

多动画效果的另一种实现方法

    PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("alpha", 1f, 0f, 1f);
    PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("scaleX", 1f, 0f, 1f);
    PropertyValuesHolder pvhZ = PropertyValuesHolder.ofFloat("scaleY", 1f, 0f, 1f);
    ObjectAnimator.ofPropertyValuesHolder(view, pvhX, pvhY, pvhZ)
        .setDuration(1000)
        .start();

10.Keyframe

PropertyValuesHolder的工厂方法里面,除了整形ofInt()、浮点型ofFloat()、Object类型ofObject()之外,另一种:ofKeyframe()。

Keyframe类型对象由一个time/value对组成,定义了指定时间点的指定值,即关键帧。

每个keyframe还能够拥有自己的interpolator,控制了前一个关键帧到这一个关键帧之间的时间动画行为。

Keyframe 对象的构造也用是工厂方法:ofInt(), ofFloat(), or ofObject()。

Keyframe对象构造完之后就能够用 ofKeyframe()工厂方法来构造PropertyValuesHolder对象。

        Keyframe kf0 = Keyframe.ofFloat(0, 1.0f);
        Keyframe kf1 = Keyframe.ofFloat(0.25f, 0.5f);
        Keyframe kf2 = Keyframe.ofFloat(0.5f, 0f);
        Keyframe kf4 = Keyframe.ofFloat(0.75f, 0.5f);
        Keyframe kf3 = Keyframe.ofFloat(1f, 1.0f);
        PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("alpha", kf0, kf1, kf2, kf4, kf3);
        ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(mView, pvhRotation);
        anim.setDuration(2000);
        anim.start();

上述代码的意思为:设置btn对象的width属性值使其:

開始时 alpha=1.0

动画開始1/4时 alpha=0.5

动画開始1/2时 alpha=0

动画開始3/4时 alpha=0.5

动画结束时 alpha=1.0

用以下的代码能够实现相同的效果(上述代码时间值是线性,变化均匀):

        ObjectAnimator oa=ObjectAnimator.ofFloat(mView, "alpha", 1.0f, 0.5f, 0f, 0.5f, 1.0f);
        oa.setDuration(2000);
        oa.start();

11.Interpolator

贝塞尔曲线

一个查看三阶贝塞尔曲线效果的站点

http://cubic-bezier.com/#.45,0,.21,1

PathInterpolator

PathInterpolator是android5.0才開始提供的一种时间时间插值器,和LinearInterpolator。AccelerateDecelerateInterpolator一样用来设置给animator或者animation的,PathInterpolator须要一段起点是(0,0),终点是(1,1)的path路径。

看它的几个构造函数:

public PathInterpolator(Path path) :自己定义的Path。可是要保证起点是(0,0)。终点是(1,1)。

public PathInterpolator(float controlX, float controlY):二阶的贝塞尔曲线,controlX和controlY是控制点的坐标

public PathInterpolator(float controlX1, float controlY1, float controlX2, float controlY2)三阶的贝塞尔曲线。(controlX1,controlY1)和(controlX2,controlY2)是两个控制点的坐标。

还能够通过xml方式定义PathInterpolator:

......
ValueAnimator trans = ValueAnimator.ofFloat(0, 1);
trans.setInterpolator(enterInterpolator);
......
public Interpolator enterInterpolator;
enterInterpolator= AnimationUtils.loadInterpolator(context,R.interpolator.enter);

enter.xml

<?xml version="1.0" encoding="utf-8"?>

<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" android:controlX1="0.45"
    android:controlY1="0" android:controlX2="0.34" android:controlY2="1" />

用android:pathData来描写叙述一个path

<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
    android:pathData="L0.3,0 C 0.5,0 0.7,1 1, 1" />

二阶贝塞尔曲线

<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
    android:controlX1="0.3"
    android:controlY1="0"/>

加减速引子

<decelerateInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
    android:factor="2.5" />

android:factor 浮点值。加减速速率,默觉得1

时间: 2024-11-10 01:07:48

Android View动画的相关文章

Android View动画效果—透明效果,旋转效果

一:动画效果 方法一:动画效果用AlphaAnimation类,直接添加 AlphaAnimation aa = new AlphaAnimation(0,1); //设置透明度 aa.setDuration(2000); //设置时间 view.startAnimation(aa); 方法二:应用xml方式 建立一个xml为aa.xml文件 <?xml version="1.0" encoding="utf-8"?> <alpha xmlns:a

Android动画——View动画

一.概述 View动画共有四种效果分别是平移动画.旋转动画.缩放动画以及透明度变化,此外帧动画也属于View动画,但实现效果与前面几种有所区别. 二.View动画的种类 四种动画分别对应四个Animation的子类TranslateAnimation.RotateAnimation.ScaleAnimation.AlphaAnimation,同时也可用XML来定义动画,分别对应标签<translate> <rotate> <scale> <alpha>,在实

Android移动view动画问题--停在动画的最后一帧(转)

Android写动画效果不是一般的麻烦,网上找了好久,终于解决了动画的问题,总结记录以共勉. 仅以水平方向移动效果做说明,垂直方向类似. public void slideview(final float p1, final float p2) { TranslateAnimation animation = new TranslateAnimation(p1, p2, 0, 0); animation.setInterpolator(new OvershootInterpolator());

Android传统View动画与Property动画基础及比较

前言:关于动画方面的知识也整理一段时间了,如题,这篇文章简单的介绍了View和Property动画的概念,如何在项目中创建资源文件,以及如何在代码中使用它们,本次整理动画的重点放在了Property动画上,下一篇文章将详细的分析Property动画几个重要的类,并分析几个开源库的实现,敬请期待. View anim (Tween/Frame) Tween动画 主要有4中:缩放.平移.渐变.旋转 文件位置: res/anim/filename.xml编译资源的数据类型:an Animation.资

有趣的动画视图集合:Android View Animations

Android View Animations这个项目收集了各种有趣的动画效果. 所有效果: Attension Flash, Pulse, RubberBand, Shake, Swing, Wobble, Bounce, Tada, StandUp, Wave Special Hinge, RollIn, RollOut,Landing,TakingOff,DropOut Bounce BounceIn, BounceInDown, BounceInLeft, BounceInRight, 

Android 动画具体解释View动画

为了让用户更舒适的在某些情况下,利用动画是那么非常有必要的.Android在3.0一旦支持两种动画Tween动漫Frame动画.Tween动画支持简单的平移,缩放,旋转,渐变.Frame动画就像Gif图通过一系列图片来模拟动画效果,而在Android 3.0以后引入了新的动画就是属性动画(property animation).Android 分享一个简单有趣的动画效果 就是利用了属性动画. 今天我们主要来学习Tween动画也就是View动画. View 动画仅仅能应用于View对象,并且仅仅支

Android移动view动画问题

http://www.cnblogs.com/eoiioe/archive/2012/08/29/2662546.html Android写动画效果不是一般的麻烦,网上找了好久,终于解决了动画的问题,总结记录以共勉. 仅以水平方向移动效果做说明,垂直方向类似. public void slideview(final float p1, final float p2) { TranslateAnimation animation = new TranslateAnimation(p1, p2, 0

Android(java)学习笔记200:Android中View动画之 XML实现 和 代码实现

1.Animation 动画类型 Android的animation由四种类型组成: XML中: alph 渐变透明度动画效果 scale 渐变尺寸伸缩动画效果 translate 画面转换位置移动动画效果 rotate 画面转移旋转动画效果 JavaCode中 AlphaAnimation 渐变透明度动画效果 ScaleAnimation 渐变尺寸伸缩动画效果 TranslateAnimation 画面转换位置移动动画效果 RotateAnimation 画面转移旋转动画效果  2.Andro

Android视图动画-View Animation

视图动画主要有两种: 一.Tween Animation译为"补间动画" 1.scale译为"规模.比例",是对View进行特定范围的缩放2.alpha通过改变View的透明度实现View隐现的效果3.translate译为"转移",是对View进行位置的移动4.rotate译为"旋转",是让View围绕特定的点进行旋转PS:所有View的移动.隐藏.旋转仅仅是看到的动画效果,实际View的位置/大小/比例并没有发生本质上的改