综述
本文主要包括Android中动画、Drawable、Canvas、openGL以及硬件加速部分内容。
对于openGL可以使用framework层本身的API也可以使用本地的NDK进行编写,其中NDK编写的程序的运行效率更高。
Android中动画分为两类:属性动画和视图动画。
属性动画能对非View和View对象进行操作。而且其定义的动画运行的健壮性更好。
视图动画是View对象进行操作,只是改变透明的,旋转,图片拉伸收缩。不能对背景颜色等进行操作。视图动画的另一个缺点是,只能够在View画的位置进行修改,而不是View的真实位置。其优势是需要很少的代码并且建立的速度比较快。
属性动画:对单独的属性进行操作。
视图动画分为:
1)补间动画。对一张图片本身进行拉伸、透明度的修改和旋转等。
2)帧动画。对多张图片施加的动画。
一、属性动画。
这是Android动画中最为健壮的动画内容。你可以对在屏幕显示或者没有显示的任何对象的属性进行操作。你可以对其要进行的操作和动画持续时间进行设置。
1)可以为动画指定持续时间,默认为300ms,并且指定动画的重复次数。
2)可以将动画分成逻辑上的组,也可以将一个动画设定在一个具体动画结束之后再进行。
3)为动画指定帧刷新延时。默认情况下是10ms但是最终是多长时间还是用系统当时运行的状态决定的。
1.属性动画。对于非View类型的只能使用property动画。
1)工作原理
Animator类是属性动画的基类,有三个派生类。
ValueAnimator --> ObjectAnimator AnimatorSet
其中ValueAnimator功能最为全面,objectAnimator是其派生类该类有了一些限制。AnimatorSet用于编排一段动画。
Evaluator用来让告诉属性动画如何计算值,其包含一个由Animator提供的时间数据,动画的开始时间和停止时间,并根据时间计算出这些属性的值。
Evaluators的类型:Int Float Argb(用于计算颜色的) TypeEvaluators(用户可以继承该类实现自己的Evaluators)。
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); } }
插值:定义了动画上的特定值是如何计算为时间的函数的。
Table 3. Interpolators
Class/Interface | Description |
---|---|
AccelerateDecelerateInterpolator | An interpolator whose rate of change starts and ends slowly but accelerates through the middle. |
AccelerateInterpolator | An interpolator whose rate of change starts out slowly and then accelerates. |
AnticipateInterpolator | An interpolator whose change starts backward then flings forward. |
AnticipateOvershootInterpolator | An interpolator whose change starts backward, flings forward and overshoots the target value, then finally goes back to the final value. |
BounceInterpolator | An interpolator whose change bounces at the end. |
CycleInterpolator | An interpolator whose animation repeats for a specified number of cycles. |
DecelerateInterpolator | An interpolator whose rate of change starts out quickly and and then decelerates. |
LinearInterpolator | An interpolator whose rate of change is constant. |
OvershootInterpolator | An interpolator whose change flings forward and overshoots the last value then comes back. |
TimeInterpolator | An interface that allows you to implement your own interpolator. |
ValueAnimator animation = ValueAnimator.ofFloat(0f, 1f); animation.setDuration(1000); animation.start();当然上述代码没有对特定的对象进行处理。所以在实际应用中可以使用AnimatorListener对动画进行监听然后动态的修改动画。
Animator.AnimatorListener
onAnimationStart()
- Called when the animation starts.onAnimationEnd()
- Called when the animation ends.onAnimationRepeat()
- Called when the animation repeats itself.onAnimationCancel()
- Called when the animation is canceled. A cancelled animation also callsonAnimationEnd()
, regardless of how they were ended.
所有的对View操作的setter方法(如setApha)的调用后都必须要调用invalidate方法然View重新绘制,这些方法中已经对invalidate方法进行了正确的调用。
ValueAnimatorAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f); fadeAnim.setDuration(250); fadeAnim.addListener(new AnimatorListenerAdapter() { public void onAnimationEnd(Animator animation) { balls.remove(((ObjectAnimator)animation).getTarget()); }AnimatorListenerAdapter对AnimatorUpdateListener进行了空实现,这样你就可以重写你需要的方法了。
ObjectAnimator中结合了时间引擎和属性值的计算的能力对特定对象上的属性就行操作。并且使用该类你就不用再使用监听器对动画进行处理了,因为其会对动画自动进行处理。
ObjectAnimator anim = ObjectAnimator.ofFloat(foo, "alpha", 0f, 1f); anim.setDuration(1000); anim.start();其和ValueAnimator不同在于:必须在创建动画时就指定目标对象。
在该类中的目标对象必须有一个setter方法。如setFoo这是因为在自动修改的时候回去调用这个方法。如果没有改方法,那么你需要使用一个包裹类将该对象包裹起来,然后在提供setter方法。对于foo对象的所有的属性你必须为其提供相应的getter方法。因为程序需要调用getter方法来获取其当前设定的值。
使用AnimatorSet编排多个动画。
- Plays
bounceAnim
. - Plays
squashAnim1
,squashAnim2
,stretchAnim1
, andstretchAnim2
at the same time. - Plays
bounceBackAnim
. - Plays
fadeAnim
.
AnimatorSet bouncer = new AnimatorSet(); bouncer.play(bounceAnim).before(squashAnim1); bouncer.play(squashAnim1).with(squashAnim2); bouncer.play(squashAnim1).with(stretchAnim1); bouncer.play(squashAnim1).with(stretchAnim2); bouncer.play(bounceBackAnim).after(stretchAnim2); ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f); fadeAnim.setDuration(250); AnimatorSet animatorSet = new AnimatorSet(); animatorSet.play(bouncer).before(fadeAnim); animatorSet.start();
给布局添加动画改编ViewGroup
可以控制其中的View的出现或者消失。
APPEARING
- A flag indicating the animation that runs on items that are appearing in the container.CHANGE_APPEARING
- A flag indicating the animation that runs on items that are changing due to a new item appearing in the container.DISAPPEARING
- A flag indicating the animation that runs on items that are disappearing from the container.CHANGE_DISAPPEARING
- A flag indicating the animation that runs on items that are changing due to an item disappearing from the container.
但是需要在布局文件中对其进行设置
<LinearLayout android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="match_parent" android:id="@+id/verticalContainer" android:animateLayoutChanges="true" />
关键帧keyframe
Keyframe kf0 = Keyframe.ofFloat(0f, 0f); Keyframe kf1 = Keyframe.ofFloat(.5f, 360f); Keyframe kf2 = Keyframe.ofFloat(1f, 0f); PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2); ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation) rotationAnim.setDuration(5000ms);To instantiate a
Keyframe
object, you must use one of the factory methods,
ofInt()
,
ofFloat()
, or
ofObject()
to obtain the appropriate type of
Keyframe
. You then call the
ofKeyframe()
factory method to obtain a
PropertyValuesHolder
object. Once you have the object, you can obtain an animator by passing in the
PropertyValuesHolder
object and the object to animate. The following code snippet demonstrates how to do this:
动画视图的部分说明:
translationX
andtranslationY
: These properties control where the View is located as a delta from its left and top coordinates which are set by its layout container.rotation
,rotationX
, androtationY
: These properties control the rotation in 2D (rotation
property) and 3D around the pivot point.scaleX
andscaleY
: These properties control the 2D scaling of a View around its pivot point.pivotX
andpivotY
: These properties control the location of the pivot point, around which the rotation and scaling transforms occur. By default, the pivot point is located at the center of the object.x
andy
: These are simple utility properties to describe the final location of the View in its container, as a sum of the left and top values and translationX and translationY values.alpha
: Represents the alpha transparency on the View. This value is 1 (opaque) by default, with a value of 0 representing full transparency (not visible).
To animate a property of a View object, such as its color or rotation value, all you need to do is create a property animator and specify the View property that you want to animate. For example:
ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f);视图属性动画的使用:
ViewPropertyAnimator提供一一种并行处理一个View的多个属性的解决方案。并且其运行更加高效,代码可读性高
Multiple ObjectAnimator objects
ObjectAnimator animX = ObjectAnimator.ofFloat(myView, "x", 50f); ObjectAnimator animY = ObjectAnimator.ofFloat(myView, "y", 100f); AnimatorSet animSetXY = new AnimatorSet(); animSetXY.playTogether(animX, animY); animSetXY.start();
One ObjectAnimator
PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x", 50f); PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 100f); ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvyY).start();
ViewPropertyAnimator
myView.animate().x(50f).y(100f);
属性动画提供了两种方式然用户来定制一个动画,上面都是使用代码的方式,下面讲解使用XML文件的方式。
为了区分使用了新的属性动画API的动画和之前老旧的视图动画框架的API,Android从3.1开始要求将新的动画XML文件声明在res/animator/目录下,并且ADT只识别这个目录。而不是之前的res/anim目录。
The following property animation classes have XML declaration support with the following XML tags:
ValueAnimator
-<animator>
ObjectAnimator
-<objectAnimator>
AnimatorSet
-<set>
<set android:ordering="sequentially"> <set> <objectAnimator android:propertyName="x" android:duration="500" android:valueTo="400" android:valueType="intType"/> <objectAnimator android:propertyName="y" android:duration="500" android:valueTo="300" android:valueType="intType"/> </set> <objectAnimator android:propertyName="alpha" android:duration="500" android:valueTo="1f"/> </set>
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext, R.anim.property_animator); set.setTarget(myObject); set.start();上述为调用实例。