Animation 概述
安装中的动画分为三种:补间动画(Tween Animation),帧动画(Frame Animation)和属性动画(Property Animation)。在有些资料中补间动画又被称为View Animation,帧动画又被称为drawable Animation(至少我个人感觉它们应该是一个意思,如果有不同看法,欢迎留言告知)。其中属性动画是Android3.0(API Level 11)之后才出现的。
Tween Animation 补间动画
补间动画有四个主要的实现,分别是 Translate Animation,Scale Animation , Rotate Animation , Alpha Animation 。
Transparent Animation:平移动画
主要控制位置变换的动画实现类,常使用TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta)来构造;
Scale Animation:缩放动画
Rotate Animation :旋转动画
Alpha Animation :透明度渐变动画
补间动画的Demo
代码中new动画的方式
界面布局如下:
layout中的布局文件 activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" ><LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <Button android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="click1" android:text="alpha" /> <Button android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="click2" android:text="scale" /> <Button android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="click3" android:text="rotate" /> <Button android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="click4" android:text="translate" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <Button android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="click5" android:text="一起执行" /> </LinearLayout></LinearLayout> <ImageView android:id="@+id/iv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:src="@drawable/ic_launcher" /></RelativeLayout>
MainActivity代码如下 (采用直接new的方式)
public class MainActivity extends Activity { private ImageView iv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //用来执行动画 iv = (ImageView) findViewById(R.id.iv); //给iv设置一个点击事件 iv.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //用来证明该图片的真实属性没有改变(区别于属性动画) Toast.makeText(getApplicationContext(), "你点不到我", 1).show(); } }); } // 点击按钮 执行透明动画 public void click1(View v) { //1.0 完全不透明 0.0完全透明 AlphaAnimation aa = new AlphaAnimation(1.0f, 0.0f); aa.setDuration(2000);//设置动画执行时长 aa.setRepeatCount(1);//设置动画执行的重复次数 aa.setRepeatMode(Animation.REVERSE); //设置动画执行的模式 //让iv执行动画 iv.startAnimation(aa); } // 点击按钮 执行缩放动画 缩放包括放大 缩小 public void click2(View v) { ScaleAnimation sa = new ScaleAnimation(0.2f, 2.0f, 0.2f, 2.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); sa.setDuration(2000);//设置动画执行时长 sa.setRepeatCount(1);//设置动画执行的重复次数 sa.setRepeatMode(Animation.REVERSE); //设置动画执行的模式 //让iv执行动画 iv.startAnimation(sa); } // 点击按钮 执行旋转动画 public void click3(View v) { //创建旋转动画 //RotateAnimation ra = new RotateAnimation(0, 360); RotateAnimation ra = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); ra.setDuration(2000);//设置动画执行时长 ra.setRepeatCount(1);//设置动画执行的重复次数 ra.setRepeatMode(Animation.REVERSE); //设置动画执行的模式 //让iv执行动画 iv.startAnimation(ra); } // 点击按钮 执行位移动画 public void click4(View v) { TranslateAnimation ta = new TranslateAnimation(Animation.RELATIVE_TO_PARENT, 0, Animation.RELATIVE_TO_PARENT, 0, Animation.RELATIVE_TO_PARENT, 0, Animation.RELATIVE_TO_PARENT, 0.2f); ta.setDuration(2000);//设置动画执行时长 //ta.setRepeatCount(1);//设置动画执行的重复次数 // ta.setRepeatMode(Animation.REVERSE); //设置动画执行的模式 ta.setFillAfter(true);//动画结束后 动画停留在结束的位置上 //让iv执行动画 iv.startAnimation(ta); } //让动画一起执行(动画集) public void click5(View v){ //创建动画的集合 AnimationSet set = new AnimationSet(false); AlphaAnimation aa = new AlphaAnimation(1.0f, 0.0f); aa.setDuration(2000);//设置动画执行时长 aa.setRepeatCount(1);//设置动画执行的重复次数 aa.setRepeatMode(Animation.REVERSE); //设置动画执行的模式 ScaleAnimation sa = new ScaleAnimation(0.2f, 2.0f, 0.2f, 2.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); sa.setDuration(2000);//设置动画执行时长 sa.setRepeatCount(1);//设置动画执行的重复次数 sa.setRepeatMode(Animation.REVERSE); //设置动画执行的模式 RotateAnimation ra = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); ra.setDuration(2000);//设置动画执行时长 ra.setRepeatCount(1);//设置动画执行的重复次数 ra.setRepeatMode(Animation.REVERSE); //设置动画执行的模式 //添加几个动画效果 set.addAnimation(aa); set.addAnimation(sa); set.addAnimation(ra); //执行动画 iv.startAnimation(set); } }
使用xml文件的方式
创建xml文件
对应的xml内容分别为
aplha.xml
<?xml version="1.0" encoding="utf-8"?><alpha xmlns:android="http://schemas.android.com/apk/res/android" android:duration="2000" android:fromAlpha="1.0" android:repeatCount="1" android:repeatMode="reverse" android:toAlpha="0" ></alpha>
rotate.xml
<?xml version="1.0" encoding="utf-8"?><rotate android:fromDegrees="0" android:toDegrees="360" android:pivotX="50%" android:pivotY="50%" android:repeatMode="reverse" android:repeatCount="1" android:duration="2000" xmlns:android="http://schemas.android.com/apk/res/android"> </rotate>
scale.xml
<?xml version="1.0" encoding="utf-8"?><scale android:fromXScale="0.2" android:toXScale="2.0" android:fromYScale="0.2" android:toYScale="2.0" android:pivotX="50%" android:pivotY="50%" android:repeatMode="reverse" android:repeatCount="1" android:duration="2000" xmlns:android="http://schemas.android.com/apk/res/android"> </scale>
set.xml
<?xml version="1.0" encoding="utf-8"?><set> <alpha xmlns:android="http://schemas.android.com/apk/res/android" android:duration="2000" android:fromAlpha="1.0" android:repeatCount="1" android:repeatMode="reverse" android:toAlpha="0" ></alpha> <scale android:fromXScale="0.2" android:toXScale="2.0" android:fromYScale="0.2" android:toYScale="2.0" android:pivotX="50%" android:pivotY="50%" android:repeatMode="reverse" android:repeatCount="1" android:duration="2000" xmlns:android="http://schemas.android.com/apk/res/android"> </scale> <rotate android:fromDegrees="0" android:toDegrees="360" android:pivotX="50%" android:pivotY="50%" android:repeatMode="reverse" android:repeatCount="1" android:duration="2000" xmlns:android="http://schemas.android.com/apk/res/android"> </rotate></set>
translate.xml
<?xml version="1.0" encoding="utf-8"?><translate android:fromXDelta="0%p" android:toXDelta="0%p" android:fromYDelta="0%p" android:toYDelta="20%p" android:fillAfter="true" android:repeatMode="reverse" android:duration="2000" xmlns:android="http://schemas.android.com/apk/res/android"> </translate>
layout中的布局文件 activity_main.xml (和上面new方式的大致一样,所以省略)
MainActivity.java中的 代码如下
public class MainActivity extends Activity { private ImageView iv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //用来执行动画 iv = (ImageView) findViewById(R.id.iv); //给iv设置一个点击事件 iv.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Toast.makeText(getApplicationContext(), "你点不到我", 1).show(); } }); } // 点击按钮 执行透明动画 public void click1(View v) { //1.0 完全不透明 0.0完全透明 Animation aa = AnimationUtils.loadAnimation(this, R.anim.aplha); iv.startAnimation(aa); } // 点击按钮 执行缩放动画 缩放包括放大 缩小 public void click2(View v) { Animation sa = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.scale); iv.startAnimation(sa); } // 点击按钮 执行旋转动画 public void click3(View v) { Animation ra = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.rotate); //让iv执行动画 iv.startAnimation(ra); } // 点击按钮 执行位移动画 public void click4(View v) { Animation ta = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.translate); //让iv执行动画 iv.startAnimation(ta); } //让动画一起执行 public void click5(View v){ Animation set = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.set); //执行动画 iv.startAnimation(set); }}
Frame Animation 帧动画
Frame Animation在SDK中对应drawable Aniamtion 。通过切换一系列Drawable图片来模拟动画的效果。类似于.gif 动图,(ps:一般5~8张图片/秒,可以感受到动画效果)
01、帧动画在start()之前必须stop().因为在第一次动画之后,动画会停在最后一帧,这样动画只会执行一次。
02、不要在onCreate() 方法中调用动画的 start()方法,因为此时AnimationDrawable还没有完全跟Window相关联,如果想要界面显示时就开始动画的话,需要在onWindowFoucsChanged()中调用start()。
帧动画的Demo
效果图(不知道怎么添加啊!)
对应xml文件及图片存放
xml文件内容
<?xml version="1.0" encoding="utf-8"?><animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false" > <item android:drawable="@drawable/girl_1" android:duration="200"/> <item android:drawable="@drawable/girl_2" android:duration="200"/> <item android:drawable="@drawable/girl_3" android:duration="200"/> <item android:drawable="@drawable/girl_4" android:duration="200"/> <item android:drawable="@drawable/girl_5" android:duration="200"/> <item android:drawable="@drawable/girl_5" android:duration="200"/> <item android:drawable="@drawable/girl_5" android:duration="200"/> <item android:drawable="@drawable/girl_5" android:duration="200"/> <item android:drawable="@drawable/girl_6" android:duration="200"/> <item android:drawable="@drawable/girl_7" android:duration="200"/> <item android:drawable="@drawable/girl_8" android:duration="200"/> <item android:drawable="@drawable/girl_9" android:duration="200"/> <item android:drawable="@drawable/girl_10" android:duration="200"/> <item android:drawable="@drawable/girl_11" android:duration="200"/></animation-list>
MainActivity.java文件代码如下
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //找到imageview 用来显示动画 ImageView iv = (ImageView) findViewById(R.id.iv); //加载动画图片资源 iv.setBackgroundResource(R.drawable.myanim); //获取我们要执行的资源 final AnimationDrawable anim = (AnimationDrawable) iv.getBackground(); //兼容低版本手机的写法 new Thread() { public void run() { //此方法没有异常 SystemClock.sleep(100); anim.start();//开始执行动画 }; }.start(); }}
Property Animation属性动画
由于Tween Animation不会改变资源的真实位置,所以有一些效果无法实现,比如:你希望View有一个颜色的切换动画;你希望可以使用3D旋转动画;你希望当动画停止时,View的位置就是当前的位置,这就是Property Animation产生的原因。属性动画不止可以应用于View,还可以应用于任何对象。Property Animation只是表示一个值在一段时间内的改变,当值改变时要做什么事情完全是你自己决定的。
属性动画的Demo
界面布局如下:
声明:这个Demo中代码创建动画和使用xml都存在
xml的创建和存放
oanimator.xml 代码
<?xml version="1.0" encoding="utf-8"?><animator xmlns:android="http://schemas.android.com/apk/res/android" > <objectAnimator android:propertyName="translationX" android:duration="2000" android:valueFrom="10" android:valueTo="100" ></objectAnimator></animator>
layout布局文件 activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" > <LinearLayout android:id="@+id/ll" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="translate" android:text="平移" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="scale" android:text="缩放" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="alpha" android:text="透明" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="rotate" android:text="旋转" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="fly" android:text="set" /> </LinearLayout> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/ll" android:onClick="playxml" android:text="播放xml定义的属性动画" /> <ImageView android:id="@+id/iv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:src="@drawable/ic_launcher" /></RelativeLayout>
MainActivity.java代码 如下(new方式和xml文件的方式都有)
public class MainActivity extends Activity { private ImageView iv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); iv = (ImageView) findViewById(R.id.iv); iv.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Toast.makeText(MainActivity.this, "你点不到我", 0).show(); } }); } //位移动画 public void translate(View v){ //创建属性动画 /** * target 执行的目标 * propertyName 属性名字 The name of the property being animated. * float... values 可变参数 */ //从0,向右移动50,返回到20,....(相对于图片本身的位置) ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "translationX", 0, 50,20,100,60); oa.setDuration(2000); oa.start(); //开始动画 } //缩放动画 public void scale(View v){ View view=new View(this); ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "scaleY", 0.1f, 2, 1, 2); oa.setDuration(2000); oa.start(); } //实现透明的效果 public void alpha(View v){ ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "alpha", 0, 0.5f, 0, 1,0,1); oa.setDuration(2000); oa.start(); } //实现旋转的效果 public void rotate(View v){ ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "rotation", 0, 180, 90, 360);// ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "rotationY", 0, 180, 90, 360); oa.setDuration(2000); oa.start(); } //一起飞 public void fly(View v){ AnimatorSet as = new AnimatorSet(); ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "translationX", 10, 50, 20, 100); ObjectAnimator oa2 = ObjectAnimator.ofFloat(iv, "scaleY", 0.1f, 2, 1, 2); ObjectAnimator oa3 = ObjectAnimator.ofFloat(iv, "alpha", 0, 0.5f, 0, 1); ObjectAnimator oa4 = ObjectAnimator.ofFloat(iv, "rotationY", 0, 180, 90, 360); as.setDuration(2000); as.setTarget(iv); //往集合中添加动画 //挨个飞 as.playSequentially(oa, oa2, oa3, oa4);// 一起飞// as.playTogether(oa, oa2, oa3, oa4); as.start(); } //使用xml的方式创建属性动画 public void playxml(View v){ ObjectAnimator oa = (ObjectAnimator) AnimatorInflater.loadAnimator(this, R.animator.oanimator); //设置执行目标 oa.setTarget(iv); oa.start();//开始执行 }}
动画的使用
Android 动画可以在 Java 代码中使用,也可以在 XML文件中配置之后,调用res下的资源。
☆ 在代码中使用时,直接 new 所需要的动画;
☆ 在 XML 中使用时,在创建xml文件及存放时要区别对待:
补间动画: 在 res 下新建 anim(名字文件名必须是anim)文件夹 ,创建对应的 . xml 文件(文件名自定义)
帧动画: 把所需图片和xml文件放在drawable下即可
属性动画:在 res 下新建 animator(名字文件名必须是animtor)文件夹 ,创建对应的 . xml 文件(文件名自定义)
为了区分Property animation和View animation(我认为就是指补间动画)的资源文件,从Android 3.1开始,Property animation的xml文件存在res/animator/目录下(View animation的存在res/anim/目录下), animator这个名是可选的。但是如果你想要使用Eclipse ADT plugin (ADT 11.0.0+)的布局编辑器,你就必须使用res/animator/目录,因为ADT只在该目录下寻找property animation的资源文件。
常用的方法
· setDuration 设置动画的执行时间
· setRepeatCount设置动画的重复次数
· setRepeatMode 指定重复的模式(如:反转)
· setFillAfter 指示动画指定完毕之后控件的状态是否停留在动画停止的时候
· setAnimationListener 设置动画的事件监听器
· setStartOffset 设置动画的延迟时间
· startAnimation(Animation a) 让View执行某动画
动画集
当多个动画效果作用于一个控件时,使用动画集合。在代码中使用时AnimationSet,在Xml文件中使用是<set>节点。在上文的demo中有体现。
小结
在实际开发中,比较常用的是补间动画和属性动画,在使用时首先考虑该view的真实属性是否需要改变。而帧动画只会在某些特殊连续的效果上才会使用,比如要自己做一个gif的效果。其中使用平移,缩放,旋转和明暗渐变组合起来就可以实现很多效果,而且上文中还没有提到一个东西 :插值器。在后面需要做一些比较炫的效果时我们再来详细研究一下。
版权声明:本文为博主原创文章,未经博主允许不得转载。