安卓动画学习笔记

来源:互联网 发布:域名如何icp备案 编辑:程序博客网 时间:2024/05/19 14:39

一、Drawable Animation

也就是所谓的帧动画,Frame动画。指通过指定每一帧的图片和播放时间,有序的进行播放而形成动画效果。

二、View Animation

视图动画,也就是所谓补间动画,Tween动画。指通过指定View的初始状态、变化时间、方式,通过一系列的算法去进行图形变换,从而形成动画效果,主要有Alpha、Scale、Translate、Rotate四种效果。注意:只是在视图层实现了动画效果,并没有真正改变View的属性。

三、Property Animation

属性动画,通过不断的改变View的属性,不断的重绘而形成动画效果。相比于视图动画,View的属性是真正改变了。注意:Android 3.0(API 11)以上才支持。



anim文件夹下存放tween animation和frame animation;xml文件里只有scale、rotate、translate、alpha、set五个标签;在代码中使用AnimationUtils.loadAnimation()方法加载;使用mView.setAnimation(mAnimation)为mView加载动画;使用mView.startAnimation()开启动画;

animator文件夹下存放property animation,即属性动画,xml文件里有animator、objectAnimator和set三个标签;在代码中使用AnimatorInflater.loadAnimator()方法加载动画;使用mAnimation.setTarget(mView)为mView加载动画。使用mAnimation.start()开启动画




animator代表的属性动画,每个动画只能改变一个属性值,如果需要改变多个可以考虑使用动画集。

补间动画和属性动画的区别

1.补间动画作用于view,不会改变view的属性,一个view对象有很多属性值,如:坐标,透明度等等,view的点击事件的有效点击区域并不会随着view的移动而发生改变

2.属性动画作用于view的属性,这些属性必须有get/set方法,要不属性动画将无法生效。


三种动画都是跑在UI线程中,也应了那句话,任何UI上的变化都发生在主线程中。主线程也只做更新UI的活。

/** * Start the animation playing. This version of start() takes a boolean flag that indicates * whether the animation should play in reverse. The flag is usually false, but may be set * to true if called from the reverse() method. * * <p>The animation started by calling this method will be run on the thread that called * this method. This thread should have a Looper on it (a runtime exception will be thrown if * this is not the case). Also, if the animation will animate * properties of objects in the view hierarchy, then the calling thread should be the UI * thread for that view hierarchy.</p> * * @param playBackwards Whether the ValueAnimator should start playing in reverse. */private void start(boolean playBackwards) {    if (Looper.myLooper() == null) {        throw new AndroidRuntimeException("Animators may only be run on Looper threads");    }    mReversing = playBackwards;    mPlayingBackwards = playBackwards;    if (playBackwards && mSeekFraction != -1) {        if (mSeekFraction == 0 && mCurrentIteration == 0) {            // special case: reversing from seek-to-0 should act as if not seeked at all            mSeekFraction = 0;        } else if (mRepeatCount == INFINITE) {            mSeekFraction = 1 - (mSeekFraction % 1);        } else {            mSeekFraction = 1 + mRepeatCount - (mCurrentIteration + mSeekFraction);        }        mCurrentIteration = (int) mSeekFraction;        mSeekFraction = mSeekFraction % 1;    }    if (mCurrentIteration > 0 && mRepeatMode == REVERSE &&            (mCurrentIteration < (mRepeatCount + 1) || mRepeatCount == INFINITE)) {        // if we were seeked to some other iteration in a reversing animator,        // figure out the correct direction to start playing based on the iteration        if (playBackwards) {            mPlayingBackwards = (mCurrentIteration % 2) == 0;        } else {            mPlayingBackwards = (mCurrentIteration % 2) != 0;        }    }    int prevPlayingState = mPlayingState;    mPlayingState = STOPPED;    mStarted = true;    mStartedDelay = false;    mPaused = false;    updateScaledDuration(); // in case the scale factor has changed since creation time    AnimationHandler animationHandler = getOrCreateAnimationHandler();    animationHandler.mPendingAnimations.add(this);    if (mStartDelay == 0) {        // This sets the initial value of the animation, prior to actually starting it running        if (prevPlayingState != SEEKED) {            setCurrentPlayTime(0);        }        mPlayingState = STOPPED;        mRunning = true;        notifyStartListeners();    }    animationHandler.start();}



Animation运行原理分析


http://www.cnblogs.com/kross/p/4087780.html

http://www.jianshu.com/p/fcd9c7e9937e