前言: 关于Android中的动画吧,从我一开始接触Android的时候,就陆陆续续的接触过,不得不说,动画在Android应用中应用的还是很多的,熟悉掌握了动画,也可以装装B,做出各种吊炸的效果,好吧,有的时候你觉得自己会的东西但是真正做起来的时候有感觉很吃力,这就说明你根本就没有真正的了解它,写这系列的博客也是为了复习一下Android动画,巩固一下自己所学的知识,还是一样,大牛勿喷O(∩_∩)O~
我们会从先从很基础的内容开始,然后慢慢到一些复杂的动画,一起加油吧,骚年!!
Android中的动画分为:补间动画(平移、旋转、缩放、透明度)、帧动画、属性动画。
名称 | 含义 |
---|---|
补间动画 | 补间动画与逐帧动画在本质上是不同的,逐帧动画通过连续播放图片来模拟动画的效果,而补间动画则是通过在两个关键帧之间补充渐变的动画效果来实现的。补间动画的优点是可以节省空间。 |
帧动画 | 通过播放一系列的图片从而产生动画效果,可以简单的理解为图片的切换动画,很显然,如果图片多或者很大的话,就会导致OOM。 |
属性动画 | 属性动画是API11以后才有的一个动画,(当然,我们后面也会用一个第三方的库来兼容低版本)通过不断的修改view的属性,从而达到动画的效果。 |
我们这节先来关注一下补间动画:
补间动画分为:透明度、平移、旋转、缩放。
名称 | xml中标签 | 对应的java类 | 表现形式 |
---|---|---|---|
透明度 | alpha | AlphaAnimatino | 改变view的透明度 |
平移 | translate | TranslateAnimation | 平移view |
旋转 | rotate | RotateAnimation | 旋转view |
缩放 | scale | ScaleAnimation | 缩放view |
补充一下:
在adt和as中,我们补间动画的存放位置是res/anim中:
从Animation类继承的属性
Animation类是所有动画(scale、alpha、translate、rotate)的基类。
Animation中公用的属性有:
- android:duration 动画持续时间,以毫秒为单位
- android:fillAfter 如果设置为true,控件动画结束时,将保持动画最后时的状态
- android:fillBefore 如果设置为true,控件动画结束时,还原到开始动画前的状态
- android:fillEnabled 与android:fillBefore 效果相同,都是在动画结束时,将控件还原到初始化状态
- android:repeatCount 重复次数
- android:repeatMode 重复类型,有reverse和restart两个值,reverse表示倒序回放,restart表示重新放一遍,必须与repeatCount一起使用才能看到效果。因为这里的意义是重复的类型,即回放时的动作。
- android:interpolator 设定插值器,其实就是指定的动作效果,比如物理中的需要做什么运动(匀速直线运动、曲线运动),后面会单独讲的。
- startOffset 延时多少时间后开始执行动画。
一、透明度Scale
如果你的工程中没有anim文件夹的话,自己创建一个哦,或者用as自动生成(在res目录中右键–>Android resource File):
ScaleAnimation中有两个重要的属性:
- android:fromAlpha 动画开始的透明度,从0.0 –1.0 ,0.0表示全透明,1.0表示完全不透明
- android:toAlpha 动画结束时的透明度,也是从0.0 –1.0 ,0.0表示全透明,1.0表示完全不透明
1、我们利用xml创建一个Scale动画:
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:fromAlpha="0"
android:toAlpha="1"
android:duration="800"
android:repeatCount="-1"
android:repeatMode="reverse"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
/>
2、加载xml动画:
AlphaAnimation alpha= (AlphaAnimation) AnimationUtils.loadAnimation(this,R.anim.anim_alpha1);
3、播放ScaleAnimation动画:
tv_anim.startAnimation(alpha);
4、代码很简单,实现的效果是(透明度从0到1不断的循环)我们看一下效果:
效果是看到了,接着我们用代码实现一下:
1、AlphaAnimation 的构造方法:
- AlphaAnimation(Context context, AttributeSet attrs) 从本地XML加载动画,基本不用
- AlphaAnimation(float fromAlpha, float toAlpha)
/**
* 透明度动画测试
* <?xml version="1.0" encoding="utf-8"?>
* <alpha xmlns:android="http://schemas.android.com/apk/res/android"
* android:fromAlpha="0"
* android:toAlpha="1"
* android:duration="800"
* android:repeatCount="-1"
* android:repeatMode="reverse"
* android:interpolator="@android:anim/accelerate_decelerate_interpolator"
* />
*/
public void alpha(View view) {
AlphaAnimation alpha = new AlphaAnimation(0, 1);
alpha.setDuration(800);
alpha.setRepeatCount(Animation.INFINITE);
alpha.setRepeatMode(Animation.REVERSE);
alpha.setInterpolator(new AccelerateDecelerateInterpolator());
tv_anim.startAnimation(alpha);
}
二、缩放Scale
从Animation类继承的属性
Animation类是所有动画(scale、alpha、translate、rotate)的基类。
Animation中公用的属性有:
- android:duration 动画持续时间,以毫秒为单位
- android:fillAfter 如果设置为true,控件动画结束时,将保持动画最后时的状态
- android:fillBefore 如果设置为true,控件动画结束时,还原到开始动画前的状态
- android:fillEnabled 与android:fillBefore 效果相同,都是在动画结束时,将控件还原到初始化状态
- android:repeatCount 重复次数
- android:repeatMode 重复类型,有reverse和restart两个值,reverse表示倒序回放,restart表示重新放一遍,必须与repeatCount一起使用才能看到效果。因为这里的意义是重复的类型,即回放时的动作。
- android:interpolator 设定插值器,其实就是指定的动作效果,比如物理中的需要做什么运动(匀速直线运动、曲线运动),后面会单独讲的。
- startOffset 延时多少时间后开始执行动画。
实现效果:让view在水平方向从自身(0-1.5)转变,最后停留在自身1.5倍
1、创建一个anim_scale.xml文件:
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXScale="0"
android:toXScale="1.5"
android:fromYScale="1"
android:toYScale="1"
android:pivotX="50%"
android:pivotY="50%"
android:duration="1000"
android:fillAfter="true"
/>
这里有几个重要的属性:
- android:fromXScale 起始的X方向上相对自身的缩放比例,浮点值,比如1.0代表自身无变化,0.5代表起始时缩小一倍,2.0代表放大一倍;
- android:toXScale 结尾的X方向上相对自身的缩放比例,浮点值;
- android:fromYScale 起始的Y方向上相对自身的缩放比例,浮点值,
- android:toYScale 结尾的Y方向上相对自身的缩放比例,浮点值;
- android:pivotX 缩放起点X轴坐标,可以是数值、百分数、百分数p 三种样式,比如 50、50%、50%p,当为数值时,表示在当前View的左上角,即原点处加上50px,做为起始缩放点;如果是50%,表示在当前控件的左上角加上自己宽度的50%做为起始点;如果是50%p,那么就是表示在当前的左上角加上父控件宽度的50%做为起始点x轴坐标。(具体意义,后面会举例演示)
android:pivotY 缩放起点Y轴坐标,取值及意义跟android:pivotX一样。
如果 android:pivotX=”50%” android:pivotY=”50%”不设置的话,默认从基点为控件的左上角。
下面用java代码来实现下ScaleAnimation:
放到代码中,ScaleAnimation有下面几个构造函数:
- ScaleAnimation(Context context, AttributeSet attrs) 从XML文件加载动画,基本用不到
- ScaleAnimation(float fromX, float toX, float fromY, float toY)
- ScaleAnimation(float fromX, float toX, float fromY, float toY, float pivotX, float pivotY)
- ScaleAnimation(float fromX, float toX, float fromY, float toY, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)
其中pivotXType为水平方向的基点类型,可以为:Animation.RELATIVE_TO_SELF相当于xml文件中的android:pivotX=“0%”、Animation.ABSOLUTE相当于android:pivotX=“0”、Animation.RELATIVE_TO_PARENT相当于android:pivotX=“0%p”.
这几个属性解释起来有点不太好理解,Animation.RELATIVE_TO_SELF也就是相当于自己为基准,自己的50%就是控件的中间点位置,Animation.ABSOLUTE绝对位置的意思,比如设置成50,也就是控件左上角位置加上50,Animation.RELATIVE_TO_PARENT是相对于父控件的意思,如果为50%p,也就是从控件的左上角加上父控件50%的位置。
对应的java代码:
/**
* 缩放动画
* <?xml version="1.0" encoding="utf-8"?>
* <scale xmlns:android="http://schemas.android.com/apk/res/android"
* android:fromXScale="0"
* android:toXScale="1.5"
* android:fromYScale="1"
* android:toYScale="1"
* android:pivotX="50%"
* android:pivotY="50%"
* android:duration="1000"
* android:fillAfter="true"
* />
*/
public void scale(View view) {
ScaleAnimation scale = new ScaleAnimation(0, 1.5f, 1, 1, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
scale.setDuration(1000);
scale.setFillAfter(true);
tv_anim.startAnimation(scale);
}
三、旋转RotateAnimation
Rotate标签所具有的XML属性有:
- android:fromDegrees 开始旋转的角度位置,正值代表顺时针方向度数,负值代码逆时针方向度数
- android:toDegrees 结束时旋转到的角度位置,正值代表顺时针方向度数,负值代码逆时针方向度数
- android:pivotX 缩放起点X轴坐标,可以是数值、百分数、百分数p 三种样式,比如 50、50%、50%p,具体意义已在scale标签中讲述,这里就不再重讲
- android:pivotY 缩放起点Y轴坐标,可以是数值、百分数、百分数p 三种样式,比如 50、50%、50%p
对应的构造函数有:
- RotateAnimation(Context context, AttributeSet attrs) 从本地XML文档加载动画,同样,基本不用
- RotateAnimation(float fromDegrees, float toDegrees)
- RotateAnimation(float fromDegrees, float toDegrees, float pivotX, float pivotY)
- RotateAnimation(float fromDegrees, float toDegrees, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)
RotateAnimation跟ScaleAnimation差不多,关键问题同样是pivotXType和pivotYType的选择,同样有三个取值:Animation.ABSOLUTE、Animation.RELATIVE_TO_SELF和Animation.RELATIVE_TO_PARENT;
先看看要实现的效果(使view随时针不停旋转):
对应的xml文件:
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="40"
android:toDegrees="760"
android:fillAfter="true"
android:pivotY="50%"
android:pivotX="50%"
android:duration="2000"
android:repeatCount="-1"
android:repeatMode="restart"
android:interpolator="@android:anim/linear_interpolator"
/>
对应的java代码:
/**
* 旋转动画
* <?xml version="1.0" encoding="utf-8"?>
* <rotate xmlns:android="http://schemas.android.com/apk/res/android"
* android:fromDegrees="40"
* android:toDegrees="760"
* android:fillAfter="true"
* android:pivotY="50%"
* android:pivotX="50%"
* android:duration="2000"
* android:repeatCount="-1"
* android:repeatMode="restart"
* android:interpolator="@android:anim/linear_interpolator"
* />
*/
public void rotate(View view) {
RotateAnimation rotate = new RotateAnimation(40f, 760f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotate.setDuration(2000);
rotate.setRepeatCount(Animation.INFINITE);
rotate.setRepeatMode(Animation.RESTART);
rotate.setInterpolator(new LinearInterpolator());
tv_anim.startAnimation(rotate);
}
四、平移(TranslateAnimation)
- android:fromXDelta 起始点X轴坐标,可以是数值、百分数、百分数p 三种样式,比如 50、50%、50%p,具体意义已在scale标签中讲述,这里就不再重讲
- android:fromYDelta 起始点Y轴从标,可以是数值、百分数、百分数p 三种样式;
- android:toXDelta 结束点X轴坐标
- android:toYDelta 结束点Y轴坐标
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="0"
android:toXDelta="0"
android:fromYDelta="0"
android:toYDelta="50%p"
android:repeatCount="1"
android:repeatMode="reverse"
android:duration="1000"
/>
从水平方向的0到0,竖直方向0-50%p(左上角到左上角+父控件的50%h位置)效果大致是从控件开始位置往下移动,因为设置了repeatMode=”reverse”跟android:repeatCount=”1”,所以会平移下去再回来效果;
实现的java代码:
构造方法:
- public TranslateAnimation(Context context, AttributeSet attrs) 本地加载xml,一般不用。
- public TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta)
- public TranslateAnimation(int fromXType, float fromXValue, int toXType, float toXValue,
int fromYType, float fromYValue, int toYType, float toYValue)
参数我就不解释了,跟scale的一致。
* 平移动画
* <?xml version="1.0" encoding="utf-8"?>
* <translate xmlns:android="http://schemas.android.com/apk/res/android"
* android:fromXDelta="0"
* android:toXDelta="0"
* android:fromYDelta="0"
* android:toYDelta="50%p"
* android:repeatCount="1"
* android:repeatMode="reverse"
* android:duration="1000"
* />
*/
public void translate(View view) {
TranslateAnimation translate = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_PARENT, 0.5f, Animation.RELATIVE_TO_SELF, 0);
translate.setDuration(1000);
translate.setRepeatCount(1);
translate.setRepeatMode(Animation.REVERSE);
tv_anim.startAnimation(translate);
}
五、动画集合(set)
set标签自已是没有属性的,他的属性都是从Animation继承而来,但当它们用于Set标签时,就会对Set标签下的所有子控件都产生作用。
属性有:(从Animation类继承的属性)
- android:duration 动画持续时间,以毫秒为单位
- android:fillAfter 如果设置为true,控件动画结束时,将保持动画最后时的状态
- android:fillBefore 如果设置为true,控件动画结束时,还原到开始动画前的状态
- android:fillEnabled 与android:fillBefore 效果相同,都是在动画结束时,将控件还原到初始化状态
- android:repeatCount 重复次数
- android:repeatMode 重复类型,有reverse和restart两个值,reverse表示倒序回放,restart表示重新放一遍,必须与repeatCount一起使用才能看到效果。因为这里的意义是重复的类型,即回放时的动作。
- android:interpolator 设定插值器,其实就是指定的动作效果,比如弹跳效果等,不在这小节中讲解,后面会单独列出一单讲解。
其实只要掌握了前面的几种动画了,set无非就是用一个集合把你需要播放的动画装在一起,然后进行统一的管理,比如一起播放……
比如我们要实现如下效果:
从顶部平移下来(带有透明度),然后开始旋转。
首先我们得有一个盒子装动画:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:shareInterpolator="true"
>
</set>
然后我们创建一个平移动画:
<translate
android:fromXDelta="0"
android:toXDelta="0"
android:fromYDelta="-80%p"
android:toYDelta="0"
android:duration="3000"
/>
然后创建一个透明度动画,跟translate同时播放:
<alpha
android:fromAlpha="0.5"
android:toAlpha="1"
android:duration="3000"
/>
最后平移完毕后开始旋转(创建一个旋转动画,播放时间为旋转动画执行完毕后):
<rotate
android:fromDegrees="0"
android:toDegrees="3600"
android:duration="2000"
android:pivotY="50%"
android:pivotX="50%"
android:startOffset="3000"
/>
最后把这些动画加入到集合中:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:shareInterpolator="true"
>
<translate
android:fromXDelta="0"
android:toXDelta="0"
android:fromYDelta="-80%p"
android:toYDelta="0"
android:duration="3000"
/>
<alpha
android:fromAlpha="0.5"
android:toAlpha="1"
android:duration="3000"
/>
<rotate
android:fromDegrees="0"
android:toDegrees="3600"
android:duration="2000"
android:pivotY="50%"
android:pivotX="50%"
android:startOffset="3000"
/>
</set>
看完了xml实现形式,java代码也就soeasy了:
public void set(View view) {
//创建一个动画集合
AnimationSet set = new AnimationSet(true);
set.setInterpolator(new AccelerateDecelerateInterpolator());
//创建平移动画
TranslateAnimation translate = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_PARENT, -0.8f, Animation.RELATIVE_TO_SELF, 0);
translate.setDuration(3000);
//创建透明度动画
AlphaAnimation alpha = new AlphaAnimation(0.5f, 1.0f);
alpha.setDuration(3000);
//创建旋转动画,延时2000后播放,
RotateAnimation rotate = new RotateAnimation(0, 3600, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotate.setDuration(2000);
rotate.setStartOffset(3000);
//把所有的动画加入到set集合中
set.addAnimation(translate);
set.addAnimation(alpha);
set.addAnimation(rotate);
//播放集合动画
tv_anim.startAnimation(set);
}
好啦!终于是写完了,建议小伙伴也写写博客,就像我所说的,不要觉得有些东西你觉得会了就不管了,如果能很顺利地写完一篇博客的话,说明你掌握的还不错哦!如果你觉得自己很牛了,都掌握了,但让你说又说不出来,就不要再说:”我能敲,但是不会说”这样的安慰自己的话啦,O(∩_∩)O哈哈~不扯了哈,
欢迎小伙伴们跟我一起学习,一起进步!我先给出demo的github链接了:https://github.com/913453448/AnDemo
本文部分内容参考旗舰大神的: 自定义控件三部曲之动画篇