有时要对控件添加一点动画效果,在安卓中,动画效果也是一个类,也就是Animation类。把动画效果这个类弄好后,在与控件类关联到一起,就可以实现控件有一些动作特效这样的效果了。动画效果的定义,要在xml文件中。
效果图:
屏幕录制有些卡顿。不过影响不大。
以上的例子其实只是用了ImageView这个控件,然后不同的控件用了逐渐放大,还有位置平移这个动作。
下面说说怎么实现:
先实例化Animation类:
Animation myAnimation; //通过loadAnimation函数 把动画效果的xml文件加载进来 实例化动作类 myAnimation = AnimationUtils.loadAnimation(Selection.this, R.anim.my_anim);
实现xml文件(以下给出自带的4种特效):
alpha 渐变透明度动画效果
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" > <alpha android:duration="1000" android:fromAlpha="0.0" android:toAlpha="1.0" /> <!-- 透明度控制动画效果 alpha 渐变透明度动画效果 浮点型值: fromAlpha 属性为动画起始时透明度 toAlpha 属性为动画结束时透明度 说明: 0.0表示完全透明 1.0表示完全不透明 以上值取0.0-1.0之间的float数据类型的数字 长整型值: duration 属性为动画持续时间 说明: 时间以毫秒为单位 --> </set>
scale 渐变尺寸伸缩动画效果
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" > <scale android:duration="1000" android:fillAfter="false" android:fromXScale="0.0" android:fromYScale="0.0" android:interpolator="@android:anim/accelerate_decelerate_interpolator" android:pivotX="50%" android:pivotY="50%" android:toXScale="1.4" android:toYScale="1.4" /> </set><!-- 尺寸伸缩动画效果 scale 属性:interpolator 指定一个动画的插入器 在我试验过程中,使用android.res.anim中的资源时候发现 有三种动画插入器: accelerate_decelerate_interpolator 加速-减速 动画插入器 accelerate_interpolator 加速-动画插入器 decelerate_interpolator 减速- 动画插入器 其他的属于特定的动画效果 浮点型值: fromXScale 属性为动画起始时 X坐标上的伸缩尺寸 toXScale 属性为动画结束时 X坐标上的伸缩尺寸 fromYScale 属性为动画起始时Y坐标上的伸缩尺寸 toYScale 属性为动画结束时Y坐标上的伸缩尺寸 说明: 以上四种属性值 0.0表示收缩到没有 1.0表示正常无伸缩 值小于1.0表示收缩 值大于1.0表示放大 pivotX 属性为动画相对于物件的X坐标的开始位置 pivotY 属性为动画相对于物件的Y坐标的开始位置 说明: 以上两个属性值 从0%-100%中取值 50%为物件的X或Y方向坐标上的中点位置 长整型值: duration 属性为动画持续时间 说明: 时间以毫秒为单位 布尔型值: fillAfter 属性 当设置为true ,该动画转化在动画结束后被应用
-->
translate 画面转换位置移动动画效果
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" > <translate android:duration="2000" android:fromXDelta="30" android:fromYDelta="30" android:toXDelta="-80" android:toYDelta="300" /> <!-- translate 位置转移动画效果 整型值: fromXDelta 属性为动画起始时 X坐标上的位置 toXDelta 属性为动画结束时 X坐标上的位置 fromYDelta 属性为动画起始时 Y坐标上的位置 toYDelta 属性为动画结束时 Y坐标上的位置 注意: 没有指定fromXType toXType fromYType toYType 时候, 默认是以自己为相对参照物 长整型值: duration 属性为动画持续时间 说明: 时间以毫秒为单位 --> </set>
rotate 画面转移旋转动画效果
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" > <rotate android:duration="3000" android:fromDegrees="0" android:interpolator="@android:anim/accelerate_decelerate_interpolator" android:pivotX="50%" android:pivotY="50%" android:toDegrees="+350" /> <!-- rotate 旋转动画效果 属性:interpolator 指定一个动画的插入器 在我试验过程中,使用android.res.anim中的资源时候发现 有三种动画插入器: accelerate_decelerate_interpolator 加速-减速 动画插入器 accelerate_interpolator 加速-动画插入器 decelerate_interpolator 减速- 动画插入器 其他的属于特定的动画效果 浮点数型值: fromDegrees 属性为动画起始时物件的角度 toDegrees 属性为动画结束时物件旋转的角度 可以大于360度 说明: 当角度为负数——表示逆时针旋转 当角度为正数——表示顺时针旋转 (负数from——to正数:顺时针旋转) (负数from——to负数:逆时针旋转) (正数from——to正数:顺时针旋转) (正数from——to负数:逆时针旋转) pivotX 属性为动画相对于物件的X坐标的开始位置 pivotY 属性为动画相对于物件的Y坐标的开始位置 说明: 以上两个属性值 从0%-100%中取值 50%为物件的X或Y方向坐标上的中点位置 长整型值: duration 属性为动画持续时间 说明: 时间以毫秒为单位 --> </set>
把Animation类和控件关联在一起
//控件开始动作 imgPic.startAnimation(myAnimation);
挺简单的吧,只要先实现xml文件,定义好动作的类型。再通过loadAnimation函数,用xml文件实例化Animaiton类。然后再把animaiton类和控件类关联在一起,控件就会开始有动作效果了。
不过要注意的是:animation类只能运行在主线程中!!!!!!
而且我发现一个问题,直接在代码中加入动作效果,不会自动执行。并且如果同时定义了多个有动作效果的控件的话,他们是会同时执行的,那有什么办法可以按顺序执行呢?
结合到UI还有主线程的问题,很自然就想到了Handler类。
我的解决办法是:进入activity后,开启一个新线程,这个线程按我们的需求,发消息给Handler类来执行动作,这样就可以执行了。
这是在onCreate里面的代码:
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //用于更新在主线程的UI handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.arg1){ case 0: { myAnimation = AnimationUtils.loadAnimation(Selection.this, R.anim.my_anim); imgPic.startAnimation(myAnimation); imgPic.setVisibility(View.VISIBLE); }break; case 1: { myAnimation = AnimationUtils.loadAnimation(Selection.this, R.anim.studio_anim); LWGstudio.startAnimation(myAnimation); LWGstudio.setVisibility(View.VISIBLE); }break; case 2: { backAnimation = AnimationUtils.loadAnimation(Selection.this, R.anim.back_anim); back.startAnimation(backAnimation); back.setVisibility(View.VISIBLE); }break; } } }; //透明状态栏 getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); imgPic = (ImageView)findViewById(R.id.ask); imgPic.setVisibility(View.INVISIBLE); back = (ImageView)findViewById(R.id.firstback); back.setVisibility(View.INVISIBLE); LWGstudio = (ImageView)findViewById(R.id.LWGstudio); LWGstudio.setVisibility(View.INVISIBLE); new Thread(new Runnable() { @Override public void run() { //进去隔一秒 出现askFood try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } Message ok = new Message(); ok.arg1 = 0;//区分更新什么UI handler.sendMessage(ok); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } //第一个动作执行后,隔两秒执行LWGstudio出现的动作 ok = new Message(); ok.arg1 = 1;//区分更新什么UI handler.sendMessage(ok); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } //最后出现全屏变绿的动作 ok = new Message(); ok.arg1 = 2;//区分更新什么UI handler.sendMessage(ok); } }).start(); }