3.0以前,android支持两种动画模式,tween animation,frame animation,在android3.0中又引入了一个新的动画系统:property animation,这三种动画模式在SDK中被称为property animation,view animation,drawable animation。 可通过NineOldAndroids项目在3.0之前的系统中使用Property Animation
1. View Animation(Tween Animation)
View Animation(Tween Animation):补间动画,给出两个关键帧,通过一些算法将给定属性值在给定的时间内在两个关键帧间渐变。
View animation只能应用于View对象,而且只支持一部分属性,如支持缩放旋转而不支持背景颜色的改变。
而且对于View animation,它只是改变了View对象绘制的位置,而没有改变View对象本身,比如,你有一个Button,坐标(100,100),Width:200,Height:50,而你有一个动画使其变为Width:100,Height:100,你会发现动画过程中触发按钮点击的区域仍是(100,100)-(300,150)。
View Animation就是一系列View形状的变换,如大小的缩放,透明度的改变,位置的改变,动画的定义既可以用代码定义也可以用XML定义,当然,建议用XML定义。
可以给一个View同时设置多个动画,比如从透明至不透明的淡入效果,与从小到大的放大效果,这些动画可以同时进行,也可以在一个完成之后开始另一个。
用XML定义的动画放在/res/anim/文件夹内,XML文件的根元素可以为<alpha>,<scale>,<translate>,<rotate>,interpolator元素或<set>(表示以上几个动画的集合,set可以嵌套)。默认情况下,所有动画是同时进行的,可以通过startOffset属性设置各个动画的开始偏移(开始时间)来达到动画顺序播放的效果。
可以通过设置interpolator属性改变动画渐变的方式,如AccelerateInterpolator,开始时慢,然后逐渐加快。默认为AccelerateDecelerateInterpolator。
定义好动画的XML文件后,可以通过类似下面的代码对指定View应用动画。
ImageView spaceshipImage = (ImageView)findViewById(R.id.spaceshipImage);
Animation hyperspaceJumpAnimation=AnimationUtils.loadAnimation(this, R.anim.hyperspace_jump);
spaceshipImage.startAnimation(hyperspaceJumpAnimation);
2. Drawable Animation(Frame Animation)
Drawable Animation(Frame Animation):帧动画,就像GIF图片,通过一系列Drawable依次显示来模拟动画的效果。在XML中的定义方式如下:
<animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="true"> <item android:drawable="@drawable/rocket_thrust1" android:duration="200" /> <item android:drawable="@drawable/rocket_thrust2" android:duration="200" /> <item android:drawable="@drawable/rocket_thrust3" android:duration="200" /></animation-list>
必须以<animation-list>为根元素,以<item>表示要轮换显示的图片,duration属性表示各项显示的时间。XML文件要放在/res/drawable/目录下。示例:
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
imageView = (ImageView) findViewById(R.id.imageView1);
imageView.setBackgroundResource(R.drawable.drawable_anim);
anim = (AnimationDrawable) imageView.getBackground();
}
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
anim.stop();
anim.start();
return true;
}
return super.onTouchEvent(event);
}
我在实验中遇到两点问题:
- 要在代码中调用Imageview的setBackgroundResource方法,如果直接在XML布局文件中设置其src属性当触发动画时会FC。
- 在动画start()之前要先stop(),不然在第一次动画之后会停在最后一帧,这样动画就只会触发一次。
- 最后一点是SDK中提到的,不要在onCreate中调用start,因为AnimationDrawable还没有完全跟Window相关联,如果想要界面显示时就开始动画的话,可以在onWindowFoucsChanged()中调用start()。
3. Property Animation
属性动画,这个是在Android 3.0中才引进的,以前学WPF时里面的动画机制好像就是这个,它更改的是对象的实际属性,在View Animation(Tween Animation)中,其改变的是View的绘制效果,真正的View的属性保持不变,比如无论你在对话中如何缩放Button的大小,Button的有效点击区域还是没有应用动画时的区域,其位置与大小都不变。而在Property Animation中,改变的是对象的实际属性,如Button的缩放,Button的位置与大小属性值都改变了。而且Property Animation不止可以应用于View,还可以应用于任何对象。Property Animation只是表示一个值在一段时间内的改变,当值改变时要做什么事情完全是你自己决定的。
在Property Animation中,可以对动画应用以下属性:
- Duration:动画的持续时间
- TimeInterpolation:属性值的计算方式,如先快后慢
- TypeEvaluator:根据属性的开始、结束值与TimeInterpolation计算出的因子计算出当前时间的属性值
- Repeat Count and behavoir:重复次数与方式,如播放3次、5次、无限循环,可以此动画一直重复,或播放完时再反向播放
- Animation sets:动画集合,即可以同时对一个对象应用几个动画,这些动画可以同时播放也可以对不同动画设置不同开始偏移
- Frame refreash delay:多少时间刷新一次,即每隔多少时间计算一次属性值,默认为10ms,最终刷新时间还受系统进程调度与硬件的影响
3.1 Property Animation的工作方式
对于下图的动画,这个对象的X坐标在40ms内从0移动到40 pixel.按默认的10ms刷新一次,这个对象会移动4次,每次移动40/4=10pixel。
也可以改变属性值的改变方法,即设置不同的interpolation,在下图中运动速度先逐渐增大再逐渐减小
下图显示了与上述动画相关的关键对象
ValueAnimator ?表示一个动画,包含动画的开始值,结束值,持续时间等属性。
ValueAnimator封装了一个TimeInterpolator,TimeInterpolator定义了属性值在开始值与结束值之间的插值方法。
ValueAnimator还封装了一个TypeAnimator,根据开始、结束值与TimeIniterpolator计算得到的值计算出属性值。
ValueAnimator根据动画已进行的时间跟动画总时间(duration)的比计算出一个时间因子(0~1),然后根据TimeInterpolator计算出另一个因子,最后TypeAnimator通过这个因子计算出属性值,如上例中10ms时:
首先计算出时间因子,即经过的时间百分比:t=10ms/40ms=0.25
经插值计算(inteplator)后的插值因子:大约为0.15,上述例子中用了AccelerateDecelerateInterpolator,计算公式为(input即为时间因子):
(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
最后根据TypeEvaluator计算出在10ms时的属性值:0.15*(40-0)=6pixel。上例中TypeEvaluator为FloatEvaluator,计算方法为 :
public Float evaluate(float fraction, Number startValue, Number endValue) { float startFloat = startValue.floatValue(); return startFloat + fraction * (endValue.floatValue() - startFloat);}
参数分别为上一步的插值因子,开始值与结束值。
3.2 ValueAnimator
ValueAnimator包含Property Animation动画的所有核心功能,如动画时间,开始、结束属性值,相应时间属性值计算方法等。应用Property Animation有两个步聚:
- 计算属性值
- 根据属性值执行相应的动作,如改变对象的某一属性。
ValuAnimiator只完成了第一步工作,如果要完成第二步,需要实现ValueAnimator.onUpdateListener接口,这个接口只有一个函数onAnimationUpdate(),在这个函数中会传入ValueAnimator对象做为参数,通过这个ValueAnimator对象的getAnimatedValue()函数可以得到当前的属性值如:
ValueAnimator animation = ValueAnimator.ofFloat(0f, 1f);
animation.setDuration(1000);
animation.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
Log.i("update", ((Float) animation.getAnimatedValue()).toString());
}
});
animation.setInterpolator(new CycleInterpolator(3));
animation.start();
此示例中只是向Logcat输出了一些信息,可以改为想做的工作。
Animator.AnimatorListener
onAnimationStart()onAnimationEnd()onAnimationRepeat()//当动画被取消时调用,同时会调用onAnimationEnd().onAnimationCancel()
ValueAnimator.AnimatorUpdateListener
onAnimationUpdate() //通过监听这个事件在属性的值更新时执行相应的操作,对于ValueAnimator一般要监听此事件执行相应的动作,不然Animation没意义,在ObjectAnimator(继承自ValueAnimator)中会自动更新属性,如无必要不必监听。在函数中会传递一个ValueAnimator参数,通过此参数的getAnimatedValue()取得当前动画属性值。
可以继承AnimatorListenerAdapter而不是实现AnimatorListener接口来简化操作,这个类对AnimatorListener中的函数都定义了一个空函数体,这样我们就只用定义想监听的事件而不用实现每个函数却只定义一空函数体。
ObjectAnimator oa=ObjectAnimator.ofFloat(tv, "alpha", 0f, 1f);oa.setDuration(3000);oa.addListener(new AnimatorListenerAdapter(){ public void on AnimationEnd(Animator animation){ Log.i("Animation","end"); }});oa.start();
3.3 ObjectAnimator
继承自ValueAnimator,要指定一个对象及该对象的一个属性,当属性值计算完成时自动设置为该对象的相应属性,即完成了Property Animation的全部两步操作。实际应用中一般都会用ObjectAnimator来改变某一对象的某一属性,但用ObjectAnimator有一定的限制,要想使用ObjectAnimator,应该满足以下条件:
- 对象应该有一个setter函数:set<PropertyName>(驼峰命名法)
- 如上面的例子中,像ofFloat之类的工场方法,第一个参数为对象名,第二个为属性名,后面的参数为可变参数,如果values…参数只设置了一个值的话,那么会假定为目的值,属性值的变化范围为当前值到目的值,为了获得当前值,该对象要有相应属性的getter方法:get<PropertyName>
- 如果有getter方法,其应返回值类型应与相应的setter方法的参数类型一致。
如果上述条件不满足,则不能用ObjectAnimator,应用ValueAnimator代替。
tv=(TextView)findViewById(R.id.textview1);btn=(Button)findViewById(R.id.button1);btn.setOnClickListener(new OnClickListener() {[email protected] public void onClick(View v) { ObjectAnimator oa=ObjectAnimator.ofFloat(tv, "alpha", 0f, 1f); oa.setDuration(3000); oa.start(); }});
把一个TextView的透明度在3秒内从0变至1。
根据应用动画的对象或属性的不同,可能需要在onAnimationUpdate函数中调用invalidate()函数刷新视图。
3.4 通过AnimationSet应用多个动画
AnimationSet提供了一个把多个动画组合成一个组合的机制,并可设置组中动画的时序关系,如同时播放,顺序播放等。
以下例子同时应用5个动画:
- 播放anim1;
- 同时播放anim2,anim3,anim4;
- 播放anim5。
AnimatorSet bouncer = new AnimatorSet();bouncer.play(anim1).before(anim2);bouncer.play(anim2).with(anim3);bouncer.play(anim2).with(anim4)bouncer.play(anim5).after(amin2);animatorSet.start();
3.5 TypeEvalutors
根据属性的开始、结束值与TimeInterpolation计算出的因子计算出当前时间的属性值,android提供了以下几个evalutor:
- IntEvaluator:属性的值类型为int;
- FloatEvaluator:属性的值类型为float;
- ArgbEvaluator:属性的值类型为十六进制颜色值;
- TypeEvaluator:一个接口,可以通过实现该接口自定义Evaluator。
自定义TypeEvalutor很简单,只需要实现一个方法,如FloatEvalutor的定义:
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); }}
根据动画执行的时间跟应用的Interplator,会计算出一个0~1之间的因子,即evalute函数中的fraction参数,通过上述FloatEvaluator应该很好看出其意思。
3.6 TimeInterplator
Time interplator定义了属性值变化的方式,如线性均匀改变,开始慢然后逐渐快等。在Property Animation中是TimeInterplator,在View Animation中是Interplator,这两个是一样的,在3.0之前只有Interplator,3.0之后实现代码转移至了TimeInterplator。Interplator继承自TimeInterplator,内部没有任何其他代码。
- AccelerateInterpolator ? ? 加速,开始时慢中间加速
- DecelerateInterpolator ? 减速,开始时快然后减速
- AccelerateDecelerateInterolator ? 先加速后减速,开始结束时慢,中间加速
- AnticipateInterpolator ?反向 ,先向相反方向改变一段再加速播放
- AnticipateOvershootInterpolator ? 反向加回弹,先向相反方向改变,再加速播放,会超出目的值然后缓慢移动至目的值
- BounceInterpolator ?跳跃,快到目的值时值会跳跃,如目的值100,后面的值可能依次为85,77,70,80,90,100
- CycleIinterpolator 循环,动画循环一定次数,值的改变为一正弦函数:Math.sin(2 * mCycles * Math.PI * input)
- LinearInterpolator 线性,线性均匀改变
- OvershottInterpolator ?回弹,最后超出目的值然后缓慢改变到目的值
- TimeInterpolator ? 一个接口,允许你自定义interpolator,以上几个都是实现了这个接口
3.7 当Layout改变时应用动画
ViewGroup中的子元素可以通过setVisibility使其Visible、Invisible或Gone,当有子元素可见性改变时(VISIBLE、GONE),可以向其应用动画,通过LayoutTransition类应用此类动画:
transition.setAnimator(LayoutTransition.DISAPPEARING, customDisappearingAnim);
通过setAnimator应用动画,第一个参数表示应用的情境,可以以下4种类型:
- APPEARING 当一个元素在其父元素中变为Visible时对这个元素应用动画
- CHANGE_APPEARING 当一个元素在其父元素中变为Visible时,因系统要重新布局有一些元素需要移动,对这些要移动的元素应用动画
- DISAPPEARING 当一个元素在其父元素中变为GONE时对其应用动画
- CHANGE_DISAPPEARING ?当一个元素在其父元素中变为GONE时,因系统要重新布局有一些元素需要移动,这些要移动的元素应用动画.
第二个参数为一Animator。
mTransitioner.setStagger(LayoutTransition.CHANGE_APPEARING, 30);
此函数设置动画延迟时间,参数分别为类型与时间。
3.8 Keyframes
keyFrame是一个 时间/值 对,通过它可以定义一个在特定时间的特定状态,即关键帧,而且在两个keyFrame之间可以定义不同的Interpolator,就好像多个动画的拼接,第一个动画的结束点是第二个动画的开始点。KeyFrame是抽象类,要通过ofInt(),ofFloat(),ofObject()获得适当的KeyFrame,然后通过PropertyValuesHolder.ofKeyframe获得PropertyValuesHolder对象,如以下例子:
Keyframe kf0 = Keyframe.ofInt(0, 400);Keyframe kf1 = Keyframe.ofInt(0.25f, 200);Keyframe kf2 = Keyframe.ofInt(0.5f, 400);Keyframe kf4 = Keyframe.ofInt(0.75f, 100);Keyframe kf3 = Keyframe.ofInt(1f, 500);PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("width", kf0, kf1, kf2, kf4, kf3);ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(btn2, pvhRotation);rotationAnim.setDuration(2000);
上述代码的意思为:设置btn对象的width属性值使其:
- 开始时 Width=400
- 动画开始1/4时 Width=200
- 动画开始1/2时 Width=400
- 动画开始3/4时 Width=100
- 动画结束时 Width=500
ObjectAnimator oa=ObjectAnimator.ofInt(btn2, "width", 400,200,400,100,500);
oa.setDuration(2000);
oa.start();
3.9 Animating Views
在View Animation中,对View应用Animation并没有改变View的属性,动画的实现是通过其Parent View实现的,在View被drawn时Parents View改变它的绘制参数,draw后再改变参数invalidate,这样虽然View的大小或旋转角度等改变了,但View的实际属性没变,所以有效区域还是应用动画之前的区域,比如你把一按钮放大两倍,但还是放大这前的区域可以触发点击事件。为了改变这一点,在Android 3.0中给View增加了一些参数并对这些参数增加了相应的getter/setter函数(ObjectAnimator要用这些函数改变这些属性):
- translationX,translationY: View相对于原始位置的偏移量
- rotation,rotationX,rotationY: 旋转,rotation用于2D旋转角度,3D中用到后两个
- scaleX,scaleY: 缩放比
- x,y: View的最终坐标,是View的left,top位置加上translationX,translationY
- alpha: 透明度
//应用动画之前
btn2.getLeft(); //40
btn2.getX(); //40
btn2.getTranslationX(); //0
//应用translationX动画
ObjectAnimator oa=ObjectAnimator.ofFloat(btn2,"translationX", 200);
oa.setDuration(2000);
oa.start();
/*应用translationX动画后
btn2.getLeft(); //40
btn2.getX(); //240
btn2.getTranslationX(); //200
*/
//应用X动画,假设没有应用之前的translationX动画
ObjectAnimator oa=ObjectAnimator.ofFloat(btn2, "x", 200);
oa.setDuration(2000);
oa.start();
/*应用X动画后
btn2.getLeft(); //40
btn2.getX(); //200
btn2.getTranslationX(); //160
*/
case X:
info.mTranslationX = value - mView.mLeft;
break;
Property Animation也可以在XML中定义
- <set> - AnimatorSet
- <animator> -?ValueAnimator
- <objectAnimator> -?ObjectAnimator
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext, R.anim.property_animator);
set.setTarget(myObject);
set.start();
3.10 ViewPropertyAnimator
如果需要对一个View的多个属性进行动画可以用ViewPropertyAnimator类,该类对多属性动画进行了优化,会合并一些invalidate()来减少刷新视图,该类在3.1中引入。
以下两段代码实现同样的效果:
PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x", 50f);
PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 100f);
ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvyY).start();
myView.animate().x(50f).y(100f);
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?Android中的动画类型有两种,一种是Tween动画、还有一种是Frame动画。Tween动画,这种实现方式可以使视图组件移动、放大、缩小以及产生透明度的变化;另一种Frame动画,传统的动画方法,通过顺序的播放排列好的图片来实现,类似电影。下面将一一详细介绍:
? ? ? ?本博客参考自网络,结合自己一点理解,实为学习之用,不为其他目的。
一,Tween动画
? ? ? ??又称“补间动画”、“中间动画”,最早接触Tween类是在学习Flash时候,使用ActionScript做动画的时候,使用过类Tween。
? ? ? ??Tween动画主要的功能是在绘制动画前设置动画绘制的轨迹,包括时间, 位置 ,等等。但是Tween动画的缺点是它只能设置起始点与结束点的两帧,中间过程全部由系统帮我们完成。所以在帧数比较多的游戏开发中是不太会用到它的。
? ? ? ?Tween一共提供了4中动画的效果
? ? ? ?Scale:缩放动画
? ? ? ?Rotate:旋转动画
? ? ? ?Translate:移动动画
? ? ? ?Alpha::透明渐变动画
? ? ? Tween与Frame动画类似都需要在res\anim路径下创建动画的 布局文件
???1)Scale动画
? ? ? ? ?
- import?android.app.Activity;??
- import?android.os.Bundle;??
- import?android.view.View;??
- import?android.view.View.OnClickListener;??
- import?android.view.animation.Animation;??
- import?android.view.animation.AnimationUtils;??
- import?android.widget.Button;??
- import?android.widget.ImageView;??
- ??
- public?class?ScaleActivity?extends?Activity?{??
- ??
- ??
- ????Button?mButton0?=?null;//缩小动画????
- ?????
- ????Button?mButton1?=?null;//放大动画??
- ????
- ????ImageView?mImageView?=?null;?//显示动画??
- ????
- ????Animation?mLitteAnimation?=?null;?//缩小动画??
- ??????
- ????Animation?mBigAnimation?=?null;?//放大动画??
- ??????
- ??????
- [email protected]
- ????public?void?onCreate(Bundle?savedInstanceState)?{??
- ????super.onCreate(savedInstanceState);??
- ????setContentView(R.layout.scale);??
- ??
- ????mImageView?=?(ImageView)findViewById(R.id.imageView);??
- ??
- ????/**加载缩小与放大动画**/??
- ????mLitteAnimation?=?AnimationUtils.loadAnimation(this,?R.anim.scalelitte);??
- ????mBigAnimation?=?AnimationUtils.loadAnimation(this,?R.anim.scalebig);??
- ??????
- ????mButton0?=?(Button)findViewById(R.id.button0);??
- ????mButton0.setOnClickListener(new?OnClickListener()?{??
- ??????????
- [email protected]
- ????????public?void?onClick(View?arg0)?{??
- ??????????
- ????????/**播放缩小动画**/??
- ????????mImageView.startAnimation(mLitteAnimation);??
- ??????????
- ????????}??
- ????});??
- ??????
- ????mButton1?=?(Button)findViewById(R.id.button1);??
- ????mButton1.setOnClickListener(new?OnClickListener()?{??
- ??????????
- [email protected]
- ????????public?void?onClick(View?arg0)?{??
- ????????/**播放放大动画**/??
- ????????mImageView.startAnimation(mBigAnimation);??
- ????????}??
- ????});??
- ????}??
- }??
?
?
- <scale>标签为缩放节点??
- android:fromXscale="1.0"?表示开始时X轴缩放比例为?1.0?(原图大小?*?1.0?为原图大小)??
- android:toXscale="0.0"???表示结束时X轴缩放比例为0.0(原图大小?*0.0?为缩小到看不见)??
- android:fromYscale="1.0"?表示开始时Y轴缩放比例为?1.0?(原图大小?*?1.0?为原图大小)??
- android:toYscale="0.0"???表示结束时Y轴缩放比例为0.0(原图大小?*0.0?为缩小的看不到了)??
- android:pivotX="50%"?????X轴缩放的位置为中心点??
- android:pivotY="50%"?????Y轴缩放的位置为中心点??
- android:duration="2000"??动画播放时间?这里是2000毫秒也就是2秒??
?
/anim/scalelitte.xml
?
- <?xml?version="1.0"?encoding="utf-8"?>??
- <scale???
- ??????xmlns:android="http://schemas.android.com/apk/res/android"??
- ??????android:fromXScale="0.0"???
- ??????android:toXScale="1.0"??
- ??????android:fromYScale="0.0"???
- ??????android:toYScale="1.0"???
- ??????android:pivotX="50%"??
- ??????android:pivotY="50%"???
- ??????android:duration="2000">??
- </scale>??
/anim/scalebig.xml
- <?xml?version="1.0"?encoding="utf-8"?>??
- <scale?xmlns:android="http://schemas.android.com/apk/res/android"??
- ????????????android:fromXScale="1.0"???
- ????????????android:toXScale="0.0"??
- ????????????android:fromYScale="1.0"???
- ????????????android:toYScale="0.0"???
- ????????????android:pivotX="50%"??
- ????????????android:pivotY="50%"???
- ????????????android:duration="2000">??
- </scale>??
?
如果在代码中,加载动画,而不用xml配置动画
?
- mLitteAnimation?=??new?ScaleAnimation(0.0f,?1.0f,?0.0f,??1.0f,??
- ??????????????????Animation.RELATIVE_TO_SELF,?0.5f,????
- ??????????????????Animation.RELATIVE_TO_SELF,?0.5f);????
- ??????????????mLitteAnimation.setDuration(2000);??
?
2)Rotate旋转动画
?
- import?android.app.Activity;??
- import?android.os.Bundle;??
- import?android.view.View;??
- import?android.view.View.OnClickListener;??
- import?android.view.animation.Animation;??
- import?android.view.animation.AnimationUtils;??
- import?android.widget.Button;??
- import?android.widget.ImageView;??
- ??
- public?class?RotateActivity?extends?Activity?{??
- ??
- ????/**向左旋转动画按钮**/??
- ????Button?mButton0?=?null;??
- ????
- ????/**向右旋转动画按钮**/??
- ????Button?mButton1?=?null;??
- ????
- ????/**显示动画的ImageView**/??
- ????ImageView?mImageView?=?null;??
- ????
- ????/**向左旋转动画**/??
- ????Animation?mLeftAnimation?=?null;??
- ??????
- ????/**向右旋转动画**/??
- ????Animation?mRightAnimation?=?null;???
- ??????
- ??????
- [email protected]
- ????public?void?onCreate(Bundle?savedInstanceState)?{??
- ????super.onCreate(savedInstanceState);??
- ????setContentView(R.layout.retate);??
- ??
- ????/**拿到ImageView对象**/??
- ????mImageView?=?(ImageView)findViewById(R.id.imageView);??
- ??
- ????/**加载向左与向右旋转动画**/??
- ????mLeftAnimation?=?AnimationUtils.loadAnimation(this,?R.anim.retateleft);??
- ????mRightAnimation?=?AnimationUtils.loadAnimation(this,?R.anim.retateright);??
- ??????
- ????mButton0?=?(Button)findViewById(R.id.button0);??
- ????mButton0.setOnClickListener(new?OnClickListener()?{??
- ??????????
- [email protected]
- ????????public?void?onClick(View?arg0)?{??
- ??????????
- ????????/**播放向左旋转动画**/??
- ????????mImageView.startAnimation(mLeftAnimation);??
- ??????????
- ????????}??
- ????});??
- ??????
- ????mButton1?=?(Button)findViewById(R.id.button1);??
- ????mButton1.setOnClickListener(new?OnClickListener()?{??
- ??????????
- [email protected]
- ????????public?void?onClick(View?arg0)?{??
- ????????/**播放向右旋转动画**/??
- ????????mImageView.startAnimation(mRightAnimation);??
- ????????}??
- ????});??
- ????}??
- }??
?
?
- <rotate>标签为旋转节点??
- Tween一共为我们提供了3种动画渲染模式。??
- android:interpolator="@android:anim/accelerate_interpolator"?设置动画渲染器为加速动画(动画播放中越来越快)??
- android:interpolator="@android:anim/decelerate_interpolator"?设置动画渲染器为减速动画(动画播放中越来越慢)??
- android:interpolator="@android:anim/accelerate_decelerate_interpolator"?设置动画渲染器为先加速在减速(开始速度最快?逐渐减慢)??
- 如果不写的话?默认为匀速运动??
- ??
- android:fromDegrees="+360"设置动画开始的角度??
- android:toDegrees="0"设置动画结束的角度??
- ??
- 这个动画布局设置动画将向左做360度旋转加速运动。??
?
?
/anim/retateleft.xml
?
- <?xml?version="1.0"?encoding="utf-8"?>????
- <rotate?xmlns:android="http://schemas.android.com/apk/res/android"???
- ????????android:interpolator="@android:anim/accelerate_interpolator"????
- ????????android:fromDegrees="+360"????
- ????????android:toDegrees="0"????
- ????????android:pivotX="50%"????
- ????????android:pivotY="50%"????
- ????????android:duration="2000"???
- />????
/anim/retateright.xml
?
?
- <?xml?version="1.0"?encoding="utf-8"?>????
- <rotate??xmlns:android="http://schemas.android.com/apk/res/android"??
- ????????android:interpolator="@android:anim/decelerate_interpolator"????
- ????????android:fromDegrees="0"????
- ????????android:toDegrees="+360"????
- ????????android:pivotX="50%"????
- ????????android:pivotY="50%"????
- ????????android:duration="2000"???
- />????
?
?
?如果在代码中加载动画,而不用xml配置,代码如下
?
- mLeftAnimation?=?new?RotateAnimation(360.0f,?0.0f,??
- ????????Animation.RELATIVE_TO_SELF,?0.5f,????
- ????????Animation.RELATIVE_TO_SELF,?0.5f);??????????????
- ?????????????mLeftAnimation.setDuration(2000);????
3)Translate移动动画
- import?android.app.Activity;??
- import?android.os.Bundle;??
- import?android.view.animation.Animation;??
- import?android.view.animation.AnimationUtils;??
- import?android.widget.ImageView;??
- ??
- public?class?TranslateActivity?extends?Activity?{??
- ????/**显示动画的ImageView**/??
- ????ImageView?mImageView?=?null;??
- ????
- ????/**移动动画**/??
- ????Animation?mAnimation?=?null;??
- [email protected]
- ????public?void?onCreate(Bundle?savedInstanceState)?{??
- ????super.onCreate(savedInstanceState);??
- ????setContentView(R.layout.translate);??
- ??
- ????/**拿到ImageView对象**/??
- ????mImageView?=?(ImageView)findViewById(R.id.imageView);??
- ??
- ????/**加载移动动画**/??
- ????mAnimation?=?AnimationUtils.loadAnimation(this,?R.anim.translate);??
- ??????
- ????/**播放移动动画**/??
- ????mImageView.startAnimation(mAnimation);??
- ????}??
- }??
/layout/translate.xml
?
?
- <?xml?version="1.0"?encoding="utf-8"?>??
- <LinearLayout?xmlns:android="http://schemas.android.com/apk/res/android"??
- ????android:orientation="vertical"??
- ????android:layout_width="fill_parent"??
- ????android:layout_height="fill_parent"??
- ????>??
- ??<ImageView??
- ???android:id="@+id/imageView"??
- ???android:src="@drawable/images"??
- ???android:layout_width="wrap_content"??
- ???android:layout_height="wrap_content"??
- ?/>??
- </LinearLayout>??
/anim/translate.xml
?
?
- <?xml?version="1.0"?encoding="utf-8"?>????
- <translate??xmlns:android="http://schemas.android.com/apk/res/android"??
- ????android:fromXDelta="0"????
- ????android:toXDelta="320"????
- ????android:fromYDelta="0"????
- ????android:toYDelta="480"????
- ????android:duration="2000"????
- ????android:repeatCount="infinite"???
- />????
说明:
- <?xml?version="1.0"?encoding="utf-8"?>????
- <translate??xmlns:android="http://schemas.android.com/apk/res/android"??
- ????android:fromXDelta="0"????
- ????android:toXDelta="320"????
- ????android:fromYDelta="0"????
- ????android:toYDelta="480"????
- ????android:duration="2000"????
- ????android:repeatCount="infinite"???
- />????
代码中加载动画:
- mAnimation?=?new?TranslateAnimation(0,?320,?0,?480);??
- mAnimation.setDuration(2000);????
4 )Alpha:透明渐变动画
- import?android.app.Activity;??
- import?android.os.Bundle;??
- import?android.view.animation.Animation;??
- import?android.view.animation.AnimationUtils;??
- import?android.widget.ImageView;??
- ??
- public?class?AlphaActivity?extends?Activity?{??
- ????/**显示动画的ImageView**/??
- ????ImageView?mImageView?=?null;??
- ????
- ????/**透明动画**/??
- ????Animation?mAnimation?=?null;??
- [email protected]
- ????public?void?onCreate(Bundle?savedInstanceState)?{??
- ????super.onCreate(savedInstanceState);??
- ????setContentView(R.layout.translate);??
- ??
- ????/**拿到ImageView对象**/??
- ????mImageView?=?(ImageView)findViewById(R.id.imageView);??
- ??
- ????/**加载透明动画**/??
- ????mAnimation?=?AnimationUtils.loadAnimation(this,?R.anim.alpha);??
- ??????
- ????/**播放透明动画**/??
- ????mImageView.startAnimation(mAnimation);??
- ????}??
- }??
/anim/alpha.xml
?
?
- <?xml?version="1.0"?encoding="utf-8"?>????
- <alpha??xmlns:android="http://schemas.android.com/apk/res/android"??
- ????android:fromAlpha="1.0"????
- ????android:toAlpha="0.0"???
- ????android:repeatCount="infinite"????
- ????android:duration="2000">????
- </alpha>????
说明:
- <alpha>标签为alpha透明度节点??
- android:fromAlpha="1.0"?设置动画起始透明度为1.0?表示完全不透明??
- android:toAlpha="0.0"设置动画结束透明度为0.0?表示完全透明??
- 也就是说alpha的取值范围为0.0?-?1.0?之间??
手动加载动画:
- mAnimation?=?new?AlphaAnimation(1.0f,?0.0f);???
- mAnimation.setDuration(2000);????
5)综合动画
可以将上面介绍的4种动画设置在一起同时进行播放,那么就须要使用<set>标签将所有须要播放的动画放在一起。
这个动画布局设置动画同时播放移动、渐变、旋转。
- import?android.app.Activity;??
- import?android.os.Bundle;??
- import?android.view.animation.Animation;??
- import?android.view.animation.AnimationUtils;??
- import?android.widget.ImageView;??
- ??
- public?class?AllActivity?extends?Activity?{??
- ??
- ????ImageView?mImageView?=?null;??
- ????
- ????Animation?mAnimation?=?null;??
- [email protected]
- ????public?void?onCreate(Bundle?savedInstanceState)?{??
- ????super.onCreate(savedInstanceState);??
- ????setContentView(R.layout.translate);??
- ??
- ????mImageView?=?(ImageView)findViewById(R.id.imageView);??
- ??
- ????mAnimation?=?AnimationUtils.loadAnimation(this,?R.anim.all);??
- ??????
- ????mImageView.startAnimation(mAnimation);??
- ????}??
- }??
/anim/all.xml
?
?
- <?xml?version="1.0"?encoding="utf-8"?>????
- <set?xmlns:android="http://schemas.android.com/apk/res/android">????
- ????<rotate????
- ????????android:interpolator="@android:anim/accelerate_interpolator"????
- ????????android:fromDegrees="+360"????
- ????????android:toDegrees="0"????
- ????????android:pivotX="50%"????
- ????????android:pivotY="50%"????
- ????????android:duration="2000"???
- ????????android:repeatCount="infinite"??
- ????/>???
- ????<alpha??android:fromAlpha="1.0"????
- ????android:toAlpha="0.0"???
- ????android:repeatCount="infinite"??
- ????android:duration="2000">????
- ????</alpha>???
- ?<translate????
- ????android:fromXDelta="0"????
- ????android:toXDelta="320"????
- ????android:fromYDelta="0"????
- ????android:toYDelta="480"????
- ????android:duration="2000"????
- ????android:repeatCount="infinite"???
- />????
- </set>????
?
二,AnimationDrable实现Frame动画(设计游戏专用,嘎嘎嘎)感谢宣教主分享
?
- import?android.app.Activity;??
- import?android.graphics.drawable.AnimationDrawable;??
- import?android.os.Bundle;??
- import?android.util.Log;??
- import?android.view.View;??
- import?android.view.View.OnClickListener;??
- import?android.widget.Button;??
- import?android.widget.ImageView;??
- import?android.widget.RadioButton;??
- import?android.widget.RadioGroup;??
- import?android.widget.SeekBar;??
- import?android.widget.SeekBar.OnSeekBarChangeListener;??
- ??
- public?class?SimpleActivity?extends?Activity?{??
- ??
- ????/**播放动画按钮**/??
- ????Button?button0?=?null;??
- ????
- ????/**停止动画按钮**/??
- ????Button?button1?=?null;??
- ??????
- ????/**设置动画循环选择框**/??
- ????RadioButton?radioButton0=?null;??
- ????RadioButton?radioButton1=?null;??
- ????RadioGroup??radioGroup?=?null;??
- ????
- ????/**拖动图片修改Alpha值**/??
- ????SeekBar?seekbar?=?null;??
- ????
- ????/**绘制动画View**/??
- ????ImageView?imageView?=?null;??
- ?????
- ????/**绘制动画对象**/??
- ????AnimationDrawable?animationDrawable?=?null;??
- [email protected]
- ????public?void?onCreate(Bundle?savedInstanceState)?{??
- ????super.onCreate(savedInstanceState);??
- ????setContentView(R.layout.simple);??
- ??
- ????/**拿到ImageView对象**/??
- ????imageView?=?(ImageView)findViewById(R.id.imageView);??
- ????/**通过ImageView对象拿到背景显示的AnimationDrawable**/??
- ????animationDrawable?=?(AnimationDrawable)?imageView.getBackground();??
- ??????
- ??????
- ????/**开始播放动画**/??
- ????button0?=?(Button)findViewById(R.id.button0);??
- ????button0.setOnClickListener(new?OnClickListener()?{??
- ??????????
- [email protected]
- ????????public?void?onClick(View?arg0)?{??
- ????????/**播放动画**/??
- ????????if(!animationDrawable.isRunning())?{??
- ????????????animationDrawable.start();??
- ????????}??
- ????????}??
- ????});??
- ??????
- ????/**停止播放动画**/??
- ????button1?=?(Button)findViewById(R.id.button1);??
- ????button1.setOnClickListener(new?OnClickListener()?{??
- ??????????
- [email protected]
- ????????public?void?onClick(View?arg0)?{??
- ????????/**停止动画**/??
- ????????if(animationDrawable.isRunning())?{??
- ????????????animationDrawable.stop();??
- ????????}??
- ????????}??
- ????});??
- ????/**单次播放**/??
- ????radioButton0?=?(RadioButton)findViewById(R.id.checkbox0);??
- ????/**循环播放**/??
- ????radioButton1?=?(RadioButton)findViewById(R.id.checkbox1);??
- ????/**单选列表组**/??
- ????radioGroup?=?(RadioGroup)findViewById(R.id.radiogroup);??
- ????radioGroup.setOnCheckedChangeListener(new?RadioGroup.OnCheckedChangeListener()?{??
- ??????????
- [email protected]
- ????????public?void?onCheckedChanged(RadioGroup?radioGroup,?int?checkID)?{??
- ????????if(checkID?==?radioButton0.getId())?{??
- ????????????//设置单次播放??
- ????????????animationDrawable.setOneShot(true);??
- ????????}else?if?(checkID?==?radioButton1.getId())?{??
- ????????????//设置循环播放??
- ????????????animationDrawable.setOneShot(false);??
- ????????}??
- ??????????
- ????????//发生改变后让动画重新播放??
- ????????animationDrawable.stop();??
- ????????animationDrawable.start();??
- ????????}??
- ????});??
- ??????
- ????/**监听的进度条修改透明度**/??
- ????seekbar?=?(SeekBar)findViewById(R.id.seekBar);??
- ????seekbar.setOnSeekBarChangeListener(new?OnSeekBarChangeListener()?{??
- [email protected]
- ????????public?void?onStopTrackingTouch(SeekBar?seekBar)?{??
- ??????????
- ????????}??
- [email protected]
- ????????public?void?onStartTrackingTouch(SeekBar?seekBar)?{??
- ??????????
- ????????}??
- [email protected]
- ????????public?void?onProgressChanged(SeekBar?seekBar,?int?progress,?boolean?frameTouch)?{??
- ????????/**设置动画Alpha值**/??
- ????????animationDrawable.setAlpha(progress);??
- ????????/**通知imageView?刷新屏幕**/??
- ????????imageView.postInvalidate();??
- ????????}??
- ????});??
- ??????
- ????}??
- }??
/layout/simple.xml
?
?
- <?xml?version="1.0"?encoding="utf-8"?>??
- <LinearLayout?xmlns:android="http://schemas.android.com/apk/res/android"??
- ????android:orientation="vertical"??
- ????android:layout_width="fill_parent"??
- ????android:layout_height="fill_parent"??
- ????>??
- <LinearLayout???
- ????android:orientation="horizontal"??
- ????android:layout_width="wrap_content"??
- ????android:layout_height="wrap_content"??
- ????>??
- ?<Button??
- ???android:id="@+id/button0"??
- ???android:layout_width="wrap_content"??
- ???android:layout_height="wrap_content"??
- ???android:text="播放动画"??
- ?/>??
- ???
- ??<Button??
- ???android:id="@+id/button1"??
- ???android:layout_width="wrap_content"??
- ???android:layout_height="wrap_content"??
- ???android:text="停止动画"??
- ?/>??
- ?</LinearLayout>??
- ?????
- ?<RadioGroup?android:id="@+id/radiogroup"??
- ?????android:layout_width="wrap_content"??
- ?????android:layout_height="wrap_content"??
- ?????android:orientation="horizontal">??
- ???<RadioButton??
- ?????android:id="@+id/checkbox0"??
- ?????android:layout_width="wrap_content"??
- ?????android:layout_height="wrap_content"??
- ?????android:checked="true"??
- ?????android:text="单次播放"??
- ???/>??
- ??<RadioButton??
- ????android:id="@+id/checkbox1"??
- ????android:layout_width="wrap_content"??
- ????android:layout_height="wrap_content"??
- ????android:text="循环播放"??
- ???/>??
- ???</RadioGroup>??
- ?????
- ????<TextView??
- ????android:layout_width="wrap_content"??
- ????android:layout_height="wrap_content"??
- ????android:text="拖动进度条修改透明度(0?-?255)之间"??
- ????/>???
- ??<SeekBar??
- ????android:id="@+id/seekBar"??
- ????android:layout_width="fill_parent"??
- ????android:layout_height="wrap_content"??
- ????android:max="256"??
- ????android:progress="256"/>??
- ??<ImageView??
- ???android:id="@+id/imageView"??
- ???android:background="@anim/animation"??
- ???android:layout_width="wrap_content"??
- ???android:layout_height="wrap_content"??
- ?/>??
- </LinearLayout>??
?
?
控制帧播放的/anim/animation.xml
?
- <animation-list?xmlns:android="http://schemas.android.com/apk/res/android"?android:oneshot="false">??
- ?<item?android:drawable="@drawable/a"?android:duration="100"?/>???
- ?<item?android:drawable="@drawable/b"?android:duration="100"?/>???
- ?<item?android:drawable="@drawable/c"?android:duration="100"?/>???
- ?<item?android:drawable="@drawable/d"?android:duration="100"?/>???
- ?<item?android:drawable="@drawable/e"?android:duration="100"?/>???
- ?<item?android:drawable="@drawable/f"?android:duration="100"?/>???
- ?<item?android:drawable="@drawable/g"?android:duration="100"?/>???
- ?<item?android:drawable="@drawable/h"?android:duration="100"?/>???
- ?<item?android:drawable="@drawable/i"?android:duration="100"?/>???
- ?<item?android:drawable="@drawable/j"?android:duration="100"?/>???
- ?</animation-list>??
? ? ? 看看内容应该是很好理解的,<animation-list>为动画的总标签,这里面放着帧动画 <item>标签,也就是说若干<item>标签的帧 组合在一起就是帧动画了。<animation-list > 标签中android:oneshot="false" 这是一个非常重要的属性,默认为false 表示 动画循环播放, 如果这里写true 则表示动画只播发一次。 <item>标签中记录着每一帧的信息android:drawable="@drawable/a"表示这一帧用的图片为"a",下面以此类推。? android:duration="100" 表示这一帧持续100毫秒,可以根据这个值来调节动画播放的速度。
这是一个比较简单的布局文件,应该都能看懂吧。? 我主要说一下 最后的这个 ImageView, 它就是用来显示我们的动画。 这里使用android:background="@anim/animation"设置这个ImageView现实的背景为一个动画,动画资源的路径为res/anim/animation.xml ? ,当然 设置background同样也可以在代码中设置。
?
- imageView.setBackgroundResource(R.anim.animation);??
通过getBackground方法就可以拿到这个animationDrawable对象。
- /**拿到ImageView对象**/??
- imageView?=?(ImageView)findViewById(R.id.imageView);??
- /**通过ImageView对象拿到背景显示的AnimationDrawable**/??
- animationDrawable?=?(AnimationDrawable)?imageView.getBackground();??
AnimationDrawable 就是用来控制这个帧动画,这个类中提供了很多方法。
animationDrawable.start(); 开始这个动画
animationDrawable.stop(); 结束这个动画
animationDrawable.setAlpha(100);设置动画的透明度, 取值范围(0 - 255)
animationDrawable.setOneShot(true); 设置单次播放
animationDrawable.setOneShot(false); 设置循环播放
animationDrawable.isRunning(); 判断动画是否正在播放
animationDrawable.getNumberOfFrames(); 得到动画的帧数。
?
?
宣教主警戒:拖动进度条设置Alpha值的时候 一定要使用 ??? imageView.postInvalidate(); 方法来通知UI线程重绘屏幕中的imageView? 否则会看不到透明的效果 。这里切记切记~~
?
?
?
?
?
?
?
?
?
?
?
?
?
?
Android的animation由四种类型组成
XML中?
alpha | 渐变透明度动画效果 |
scale | 渐变尺寸伸缩动画效果 |
translate | 画面转换位置移动动画效果 |
rotate | 画面转移旋转动画效果 |
JavaCode中?
AlphaAnimation | 渐变透明度动画效果 |
ScaleAnimation | 渐变尺寸伸缩动画效果 |
TranslateAnimation | 画面转换位置移动动画效果 |
RotateAnimation | 画面转移旋转动画效果 |
Android动画模式
Animation主要有两种动画模式:
一种是tweened animation(渐变动画)?
XML中 | JavaCode |
alpha | AlphaAnimation |
scale | ScaleAnimation |
一种是frame by frame(画面转换动画)?
XML中 | JavaCode |
translate | TranslateAnimation |
rotate | RotateAnimation |
?
?
?
?
?
?
?
?
?
?
?
?
?
?
动画与绘图综述
Android提供了一系列强大的API来把动画加到UI元素中,以及绘制订制的2D和3D图像中去。下面的几节将综述这些可用的API以及系统的功能,同时帮你做出最优的选择。
动画
Android框架提供了两种动画系统:属性动画(在Android3.0中引进)以及视图动画。这两种动画系统都有变化的选择,但是总的来说,属性动画系统是更好的选择,因为它更加灵活,并提供了更多的特性。在这两种系统之外,你可以使用帧动画,即你可以加载画图资源,并一帧接一帧的显示它们。
属性动画
:在Android3.0中引进 (API level 11), 属性动画系统可以使任何对象的属性成为动画,包括那些不会在屏幕上显示的对象。这个系统是可扩展的,而且也适用于自定义类型。
视图动画
:视图动画则是比较旧的系统,只能用于View类。它相对更容易被设置,而且足够满足许多应用的需求。
帧动画
:帧动画即一个接一个的显示Drawable资源,就像放一部电影。如果你想要的动画可以简单的用资源来表示,比如一系列的位图,那就可以用这种方法。
2D 和 3D 图形
当你写一个应用时,确定你的图形需求十分的重要,不同的图形任务最好用不同的技术来实现。举例来说,一个稳定的应用和一个互动游戏的图形和动画是有很大不同的。在这里,我们要讨论你在Android上绘图的一些方式,以及它们分别适用于哪些任务。
画布与绘图对象
:Android 提供了一系列的View?小部件来为一系列的用户界面提供广泛的支持。你也可以继承这些小部件来修改它们的外表或行为方式。除此以外,你可以你可以用Canvas类里的各种绘图方法订制2D视图,或创建绘图对象。
硬件加速
:从Android 3.0开始, 你可以通过画图API来硬件加速大多数的绘画工作,从而进一步提高它们的性能。
OpenGL
:Android 在框架API层面和NDK上都支持 OpenGL ES 1.0 和 2.0。当你想加入少数一些Canvas API不支持的图像增强时,或是你希望平台独立,而不需要高性能时,你可以使用框架API 。但使用NDK时,性能会有明显的突破,所以对于许多关注图形的应用,比如游戏,使用NDK是更有利的选择。如果你有很多的本地代码想转到Android平台上,也可以使用NDK上的OpenGL。想了解更多NDK, 请阅读NDK下载中docs/directory下的文档。