一、动画的分类
1、动画分为三类
View Animation: 视图动画(补间动画)在古老的Android版本系统中就已经提供了,只能被用来设置View的动画。
Drawable Animation: 这种动画(也叫Frame动画、帧动画)其实可以划分到视图动画的类别,专门用来一个一个的显示Drawable的resources,就像放幻灯片一样。
Property Animation: 属性动画只对Android 3.0(API 11)以上版本的Android系统才有效,这种动画可以设置给任何Object,包括那些还没有渲染到屏幕上的对象。这种动画是可扩展的,可以让你自定义任何类型和属性的动画。
二、补间动画
1、补间动画分类
补间动画可以分为四种形式,分别是 alpha(淡入淡出),rotate(旋转),scale(缩放大小),translate(位移)。一般会采用xml 文件的形式进行编写,代码会更容易书写和阅读,同时也更容易复用。Tween动画使用起来简单,效果也比较流畅,但是缺点也是很明显,首先就是拓展性太差,只能写移动、缩放、旋转、渐变四种动画,以及这四种动画的组合,不支持自定义View的拓展。其次一个致命的缺点就是动画不具有交互性,当某个元素发生View 动画后,其响应事件的位置仍然在动画进行前的地方。
注意:补间动画执行之后并未改变View的真实布局属性值,所以View 动画只能作为普通的动画效果,要避免涉及交互操作。
四种分类及跟标签
名称 | 标签 | 子类 | 效果 |
---|---|---|---|
平移动画 | <translate > | TranslateAnimation | 移动View |
缩放动画 | <scale> | ScaleAnimation | 放大或缩小View |
旋转动画 | <rotate> | RotateAnimation | 旋转View |
透明度动画 | <alpha> | AlphaAnimation | 改变View的透明度 |
动画集合 | <set> | AnimationSet | 包含若干动画 |
2、XML代码
注意:放置在res/anim/目录下
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@[package:]anim/interpolator_resource"
android:shareInterpolator=["true" | "false"] >
<alpha
android:fromAlpha="float"
android:toAlpha="float" />
<scale
android:fromXScale="float"
android:toXScale="float"
android:fromYScale="float"
android:toYScale="float"
android:pivotX="float"
android:pivotY="float" />
<translate
android:fromXDelta="float"
android:toXDelta="float"
android:fromYDelta="float"
android:toYDelta="float" />
<rotate
android:fromDegrees="float"
android:toDegrees="float"
android:pivotX="float"
android:pivotY="float" />
</set>
Animation属性详解
Animation是AnimationSet、AlphaAnimation、ScaleAnimation,RotateAnimation,TranslateAnimation的父类,所以Animation的属性,它们都有
xml属性 | java方法 | 解释 |
---|---|---|
android:detachWallpaper | setDetachWallpaper(boolean) | 是否在壁纸上运行 |
android:duration | setDuration(long) | 动画持续时间,毫秒为单位 |
android:fillAfter | setFillAfter(boolean) | 控件动画结束时是否保持动画最后的状态 |
android:fillBefore | setFillBefore(boolean) | 控件动画结束时是否还原到开始动画前的状态 |
android:fillEnabled | setFillEnabled(boolean) | 与android:fillBefore效果相同 |
android:interpolator | setInterpolator(Interpolator) | 设定插值器(指定的动画效果,譬如回弹等) |
android:repeatCount | setRepeatCount(int) | 重复次数 |
android:repeatMode | setRepeatMode(int) | 重复类型有两个值,reverse表示倒序回放,restart表示从头播放,必须与repeatCount一起使用才能看到效果 |
android:startOffset | setStartOffset(long) | 调用start函数之后等待开始运行的时间,单位为毫秒 |
android:zAdjustment | setZAdjustment(int) | 表示被设置动画的内容运行时在Z轴上的位置(top/bottom/normal),默认为normal |
无 | reset() | 重置Animation的初始化 |
无 | cancel() | 取消Animation动画 |
无 | start() | 开始Animation动画 |
无 | setAnimationListener(AnimationListener listener) | 给当前Animation设置动画监听 |
无 | hasStarted() | 判断当前Animation是否开始 |
无 | hasEnded() | 判断当前Animation是否结束 |
所有补间动画都具备以上属性,还有四种补间动画特有属性:
Alpha属性详解
xml属性 | java方法 | 解释 |
---|---|---|
android:fromAlpha | AlphaAnimation(float fromAlpha, …) | 动画开始的透明度(0.0到1.0,0.0是全透明,1.0是不透明) |
android:toAlpha | AlphaAnimation(…, float toAlpha) | 动画结束的透明度,同上 |
Rotate属性详解
xml属性 | java方法 | 解释 |
---|---|---|
android:fromDegrees | RotateAnimation(float fromDegrees, …) | 旋转开始角度,正代表顺时针度数,负代表逆时针度数 |
android:toDegrees | RotateAnimation(…, float toDegrees, …) | 旋转结束角度,正代表顺时针度数,负代表逆时针度数 |
android:pivotX | RotateAnimation(…, float pivotX, …) | 缩放起点X坐标(数值、百分数、百分数p,譬如50表示以当前View左上角坐标加50px为初始点、50%表示以当前View的左上角加上当前View宽高的50%做为初始点、50%p表示以当前View的左上角加上父控件宽高的50%做为初始点) |
android:pivotY | RotateAnimation(…, float pivotY) | 缩放起点Y坐标,同上规律 |
Scale属性详解
xml属性 | java方法 | 解释 |
---|---|---|
android:fromXScale | ScaleAnimation(float fromX, …) | 初始X轴缩放比例,1.0表示无变化 |
android:toXScale | ScaleAnimation(…, float toX, …) | 结束X轴缩放比例 |
android:fromYScale | ScaleAnimation(…, float fromY, …) | 初始Y轴缩放比例 |
android:toYScale | ScaleAnimation(…, float toY, …) | 结束Y轴缩放比例 |
android:pivotX | ScaleAnimation(…, float pivotX, …) | 缩放起点X轴坐标(数值、百分数、百分数p,譬如50表示以当前View左上角坐标加50px为初始点、50%表示以当前View的左上角加上当前View宽高的50%做为初始点、50%p表示以当前View的左上角加上父控件宽高的50%做为初始点) |
android:pivotY | ScaleAnimation(…, float pivotY) | 缩放起点Y轴坐标,同上规律 |
Translate属性详解
xml属性 | java方法 | 解释 |
---|---|---|
android:fromXDelta | TranslateAnimation(float fromXDelta, …) | 起始点X轴坐标(数值、百分数、百分数p,譬如50表示以当前View左上角坐标加50px为初始点、50%表示以当前View的左上角加上当前View宽高的50%做为初始点、50%p表示以当前View的左上角加上父控件宽高的50%做为初始点) |
android:fromYDelta | TranslateAnimation(…, float fromYDelta, …) | 起始点Y轴从标,同上规律 |
android:toXDelta | TranslateAnimation(…, float toXDelta, …) | 结束点X轴坐标,同上规律 |
android:toYDelta | TranslateAnimation(…, float toYDelta) | 结束点Y轴坐标,同上规律 |
AnimationSet详解
AnimationSet继承自Animation,是四种的组合容器管理类,没有自己特有的属性,他的属性继承自Animation,所以特别注意,当我们对set标签使用Animation的属性时会对该标签下的所有子控件都产生影响。
3、JAVA代码
使用XML定义动画
1、AnimationUtils加载出动画对象;
2、View调用开始动画方法;
Button mButton = (Button) findViewById(R.id.bt);
Animation animation = AnimationUtils.loadAnimation(this, R.anim.anim_alpha);
mButton.startAnimation(animation);
使用JAVA代码定义动画
Button mButton = (Button) findViewById(R.id.bt);
AlphaAnimation animation = new AlphaAnimation(0,1);
animation.setDuration(300);
mButton.startAnimation(animation);
4、自定义View动画
主要是初始化工作和矩阵变化工作
public class MyAnim extends Animation {
@Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
//初始化工作
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
super.applyTransformation(interpolatedTime, t);
//矩阵变化工作
}
}
5、动画Interpolator插值器详解
1、系统提供的插值器
java类 | xml id值 | 描述 |
---|---|---|
AccelerateDecelerateInterpolator | @android:anim/accelerate_decelerate_interpolator | 动画始末速率较慢,中间加速 |
AccelerateInterpolator | @android:anim/accelerate_interpolator | 动画开始速率较慢,之后慢慢加速 |
AnticipateInterpolator | @android:anim/anticipate_interpolator | 开始的时候从后向前甩 |
AnticipateOvershootInterpolator | @android:anim/anticipate_overshoot_interpolator | 类似上面 |
AnticipateInterpolator BounceInterpolator | @android:anim/bounce_interpolator | 动画结束时弹起 |
CycleInterpolator | @android:anim/cycle_interpolator | 循环播放速率改变为正弦曲线 |
DecelerateInterpolator | @android:anim/decelerate_interpolator | 动画开始快然后慢 |
LinearInterpolator | @android:anim/linear_interpolator | 动画匀速改变 |
OvershootInterpolator | @android:anim/overshoot_interpolator | 向前弹出一定值之后回到原来位置 |
PathInterpolator | 新增,定义路径坐标后按照路径坐标来跑。 |
2、自定义插值器
在res/anim/目录下创建filename.xml文件
<?xml version="1.0" encoding="utf-8"?>
<InterpolatorName xmlns:android="http://schemas.android.com/apk/res/android"
android:attribute_name="value"
/>
插值器 | 属性 | 描述 |
---|---|---|
<accelerateDecelerateInterpolator> | 无可自定义的attribute。 | 无 |
<accelerateInterpolator> | android:factor | 浮点值,加速速率(默认值为1)。 |
<anticipateInterploator> | android:tension | 浮点值,起始点后拉的张力数(默认值为2)。 |
<anticipateOvershootInterpolator> | android:tension | 浮点值,起始点后拉的张力数(默认值为2)。 |
同上 | android:extraTension | 浮点值,拉力的倍数(默认值为1.5)。 |
<bounceInterpolator> | 无可自定义的attribute。 | 无 |
<cycleInterplolator> | android:cycles | 整形,循环的个数(默认为1)。 |
<decelerateInterpolator> | android:factor | 浮点值,减速的速率(默认为1)。 |
<linearInterpolator> | 无可自定义的attribute。 | 无 |
<overshootInterpolator> | android:tension | 浮点值,超出终点后的张力(默认为2)。 |
3、Java自定义插值器的
再来看看Java自定义插值器的(Java自定义插值器其实是xml自定义的升级,也就是说如果我们修改xml的属性还不能满足需求,那就可以选择通过Java来实现)方式。
可以看见上面所有的Interpolator都实现了Interpolator接口,而Interpolator接口又继承自 TimeInterpolator,TimeInterpolator接口定义了一个float getInterpolation(float input);方法,这个方法是由系统调用的,其中的参数input代表动画的时间,在0和1之间,也就是开始和结束之间。
如下就是一个动画始末速率较慢、中间加速的AccelerateDecelerateInterpolator插值器:
public class AccelerateDecelerateInterpolator extends BaseInterpolator
implements NativeInterpolatorFactory {
......
public float getInterpolation(float input) {
return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
}
......
}
6、View动画的特殊使用场景
1、LayoutAnimation
LayoutAnimation作用于ViewGroup,为ViewGroup指定一个动画,这样它的子元素都会具有这种动画效果,常被用于ListView.
步骤:
- 定义LayoutAnimation(在res/anim文件夹下创建xml文件)
<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
android:delay="0.5"
android:animationOrder="normal"
android:animation="@anim/anim_item"
/>
xml属性 | 解释 |
---|---|
android:delay | 表示子元素开始动画的时间延迟,比如子元素入场动画的时间周期为 300ms,那么0.5表示每个子元素都需要延迟 150ms 才能播放入场动画。总体来说,第一个子元素延迟 150ms开始播放入场动画,第2个子元素延迟 300ms 开始播放入场动画,依次类推。 |
android:animationOrder | 表示子元素动画的顺序,有三种选项:normal、reverse 和random,其中 normal 表示顺序显示,即排在前面的子元素先开始播放入场动画:reverse 表示逆向显示,即排在后面的子元素先开始播放入场动画:random 则是随机播放入场动画。 |
android:animation | 为子元素指定具体的入场动画 |
- 定义子元素入场动画,即上面的anim_item(在res/anim文件夹下创建xml文件)
- 为ViewGroup指定android:layoutAnimation属性;
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layoutAnimation="@anim/anim_layout"/>
2、Activity的切换效果
Activity有默认的切换效果,我们也可以自定义,主要用到:
overridePendingTransition(int entryAnim,int exitAnim)这个方法;
这个方法必须在startActivity()或者finish()方法之后调用才生效
entryAnim:Activity被打开时,所需要的动画资源id;
exitAnim:Activity被暂停时,所需要的动画资源id;
Fragment切换动画:
FragmentTransation中的setCustomAnimations()方法;
三、帧动画
帧动画就是顺序播放一组预先定义好的图片,类似于电影播放;通过AnimationDrawable来使用帧动画;这种动画的实质其实是Drawable,所以这种动画的XML定义方式文件一般放在res/drawable/目录下
1、定义xml文件(res/drawable/目录下)
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item
android:drawable="@mipmap/img_miao1"
android:duration="80" />
<item
android:drawable="@mipmap/img_miao2"
android:duration="80" />
<item
android:drawable="@mipmap/img_miao3"
android:duration="80" />
...
</animation-list>
android:oneshot true代表只执行一次,false循环执行。
<item> 类似一帧的动画资源
android:drawable 一个frame的Drawable资源。
android:duration 一个frame显示多长时间。
2、将上述Drawable作为Viwe背景,并通过Drawable来播放
<Button
android:id="@+id/button"
android:layout_width="120dp"
android:layout_height="120dp"
android:layout_gravity="center"
android:background="@anim/miao_gif" />
AnimationDrawable anim = (AnimationDrawable) button.getBackground();
anim.start();
注意,AnimationDrawable的start()方法不能在Activity的onCreate方法中调运,因为AnimationDrawable还未完全附着到window上,所以最好的调运时机是onWindowFocusChanged()方法中。
四、属性动画
1、属性动画简介
Android 3.0以后引入了属性动画,属性动画实现原理就是修改控件的属性值实现的动画。
可修改几个常用的View属性成员:
属性 | 解释 |
---|---|
translationX,translationY: | 控制View的位置,值是相对于View容器左上角坐标的偏移。 |
rotationX,rotationY: | 控制相对于轴心旋转。 |
x,y: | 控制View在容器中的位置,即左上角坐标加上translationX和translationY的值。 |
alpha: | 控制View对象的alpha透明度值。 |
属性动画的基类
/**
* This is the superclass for classes which provide basic support for animations which can be
* started, ended, and have <code>AnimatorListeners</code> added to them.
*/
public abstract class Animator implements Cloneable {
......
}
1.png
可以看出来继承关系使用属性动画的重点就在于AnimatorSet、ObjectAnimator、TimeAnimator、ValueAnimator;
java类名 | xml关键字 | 描述信息 |
---|---|---|
ValueAnimator |
<animator> 放置在res/animator/目录下 |
在一个特定的时间里执行一个动画 |
TimeAnimator | 不支持 | 时序监听回调工具 |
ObjectAnimator | <objectAnimator>放置在res/animator/目录下 | 一个对象的一个属性动画 |
AnimatorSet |
<set> 放置在res/animator/目录下 |
动画集合 |
2、XML实现方式
注意:放置在res/animator/目录下
<set
android:ordering=["together" | "sequentially"]>
<objectAnimator
android:propertyName="string"
android:duration="int"
android:valueFrom="float | int | color"
android:valueTo="float | int | color"
android:startOffset="int"
android:repeatCount="int"
android:repeatMode=["repeat" | "reverse"]
android:valueType=["intType" | "floatType"]/>
<animator
android:duration="int"
android:valueFrom="float | int | color"
android:valueTo="float | int | color"
android:startOffset="int"
android:repeatCount="int"
android:repeatMode=["repeat" | "reverse"]
android:valueType=["intType" | "floatType"]/>
</set>
属性动画节点有ValueAnimator、ObjectAnimator、AnimatorSet
Set属性详解
xml属性 | 描述信息 |
---|---|
android:ordering | 控制子动画启动方式是先后有序的还是同时进行。sequentially:动画按照先后顺序;together(默认):动画同时启动; |
objectAnimator属性和ValueAnimator属性详解
xml属性 | 描述信息 |
---|---|
android:propertyName | String类型,必须要设置的节点属性,代表要执行动画的属性(通过名字引用),辟如你可以指定了一个View的”alpha” 或者 “backgroundColor” ,这个objectAnimator元素没有对外说明target属性,所以你不能在XML中设置执行这个动画,必须通过调用 loadAnimator()方法加载你的XML动画资源,然后调用setTarget()应用到具备这个属性的目标对象上(譬如TextView)。 |
android:valueTo | float、int或者color类型,必须要设置的节点属性,表明动画结束的点;如果是颜色的话,由6位十六进制的数字表示。 |
android:valueFrom | 相对应valueTo,动画的起始点,如果没有指定,系统会通过属性的get方法获取,颜色也是6位十六进制的数字表示。 |
android:duration | 动画的时长,int类型,以毫秒为单位,默认为300毫秒。 |
android:startOffset | 动画延迟的时间,从调用start方法后开始计算,int型,毫秒为单位。 |
android:repeatCount | 一个动画的重复次数,int型,”-1“表示无限循环,”1“表示动画在第一次执行完成后重复执行一次,也就是两次,默认为0,不重复执行。 |
android:repeatMode | 重复模式:int型,当一个动画执行完的时候应该如何处理。该值必须是正数或者是-1,“reverse”会使得按照动画向相反的方向执行,可实现类似钟摆效果。“repeat”会使得动画每次都从头开始循环。 |
android:valueType | 关键参数,如果该value是一个颜色,那么就不需要指定,因为动画框架会自动的处理颜色值。有intType和floatType(默认)两种:分别说明动画值为int和float型。 |
XML文件在Java代码中使用
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext,
R.animtor.property_animator);
set.setTarget(myObject);
set.start();
3、JAVA实现方式
1. ObjectAnimator:继承自ValueAnimator,允许你指定要进行动画的对象以及该对象 的一个属性。该类会根据计算得到的新值自动更新属性。
ObjectAnimator类提供了ofInt、ofFloat、ofObject这个三个常用的方法,这些方法都是设置动画作用的元素、属性、开始、结束等任意属性值。当属性值(上面方法的参数)只设置一个时就把通过getXXX反射获取的值作为起点,设置的值作为终点;如果设置两个(参数),那么一个是开始、另一个是结束。
特别注意:ObjectAnimator的动画原理是不停的调用setXXX方法更新属性值,所有使用ObjectAnimator更新属性时的前提是Object必须声明有getXXX和setXXX方法。
我们通常使用ObjectAnimator设置View已知的属性来生成动画,而一般View已知属性变化时都会主动触发重绘操作,所以动画会自动实现;但是也有特殊情况,譬如作用Object不是View,或者作用的属性没有触发重绘,或者我们在重绘时需要做自己的操作,那都可以通过如下方法手动设置:
自动更新属性重绘操作
ObjectAnimator.ofFloat(view, "rotationY", 0.0f, 360.0f).setDuration(1000).start();
手动更新属性
ObjectAnimator mObjectAnimator= ObjectAnimator.ofInt(view, "customerDefineAnyThingName", 0, 1).setDuration(2000);
mObjectAnimator.addUpdateListener(new AnimatorUpdateListener()
{
@Override
public void onAnimationUpdate(ValueAnimator animation)
{
//int value = animation.getAnimatedValue(); 可以获取当前属性值
//view.postInvalidate(); 可以主动刷新
//view.setXXX(value);
//view.setXXX(value);
//......可以批量修改属性
}
});
根据path 轨迹的方式来实现动画的效果
ObjectAnimator animator = ObjectAnimator.ofFloat(iv_circle, View.X, View.Y, curvepath.path);
animator.setDuration(2000);
animator.start();
2. PropertyValuesHolder:多属性动画同时工作管理类。有时候我们需要同时修改多个属性,那就可以用到此类,具体如下:
PropertyValuesHolder a1 = PropertyValuesHolder.ofFloat("alpha", 0f, 1f);
PropertyValuesHolder a2 = PropertyValuesHolder.ofFloat("translationY", 0, viewWidth);
......
ObjectAnimator.ofPropertyValuesHolder(view, a1, a2, ......).setDuration(1000).start();
3. ValueAnimator:属性动画中的时间驱动,管理着动画时间的开始、结束属性值,相应时间属性值计算方法等。包含所有计算动画值的核心函数以及每一个动画时间节点上的信息、一个动画是否重复、是否监听更新事件等,并且还可以设置自定义的计算类型。
特别注意:ValueAnimator只是动画计算管理驱动,设置了作用目标,但没有设置属性,需要通过updateListener里设置属性才会生效。
ValueAnimator animator = ValueAnimator.ofFloat(0, mContentHeight); //定义动画
animator.setTarget(view); //设置作用目标
animator.setDuration(5000).start();
animator.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation){
float value = (float) animation.getAnimatedValue();
view.setXXX(value); //必须通过这里设置属性值才有效
view.mXXX = value; //不需要setXXX属性方法
}
});
4. AnimationSet:动画集合,提供把多个动画组合成一个组合的机制,并可设置动画的时序关系,如同时播放、顺序播放或延迟播放。具体使用方法比较简单,如下:
ObjectAnimator a1 = ObjectAnimator.ofFloat(view, "alpha", 1.0f, 0f);
ObjectAnimator a2 = ObjectAnimator.ofFloat(view, "translationY", 0f, viewWidth);
......
AnimatorSet animSet = new AnimatorSet();
animSet.setDuration(5000);
animSet.setInterpolator(new LinearInterpolator());
//animSet.playTogether(a1, a2, ...); //两个动画同时执行
animSet.play(a1).after(a2); //先后执行
......//其他组合方式
animSet.start();
5. Interpolator插值器
TimeInterpolator:时间插值器;
作用:根据时间流逝的百分比来计算出当前属性值改变的百分比;
TimeInterpolator的子类Interpolator,以下继承自Interpolator;
系统提供分类:
AccelerateDecelerateInterolator:先加速后减速。
AccelerateInterpolator:加速。
DecelerateInterpolator:减速。
AnticipateInterpolator:先向相反方向改变一段再加速播放。
AnticipateOvershootInterpolator:先向相反方向改变,再加速播放,会超出目标值然后缓慢移动至目标值,类似于弹簧回弹。
BounceInterpolator:快到目标值时值会跳跃。
CycleIinterpolator:动画循环一定次数,值的改变为一正弦函数:Math.sin(2 * mCycles * Math.PI * input)。
LinearInterpolator:线性均匀改变。
OvershottInterpolator:最后超出目标值然后缓慢改变到目标值。
TimeInterpolator:一个允许自定义Interpolator的接口,以上都实现了该接口。
自定义插值器:
//开始很慢然后不断加速的插值器。
public class AccelerateInterpolator implements Interpolator {
private final float mFactor;
private final double mDoubleFactor;
public AccelerateInterpolator() {
mFactor = 1.0f;
mDoubleFactor = 2.0;
}
......
//input 0到1.0。表示动画当前点的值,0表示开头,1表示结尾。
//return 插值。值可以大于1超出目标值,也可以小于0突破低值。
@Override
public float getInterpolation(float input) {
//实现核心代码块
if (mFactor == 1.0f) {
return input * input;
} else {
return (float)Math.pow(input, mDoubleFactor);
}
}
}
6. Evaluator估值器
TypeEvaluator:类型估值算法,也叫估值器;
作用:根据当前属性改变的百分比来计算改变后的属性值;
TypeEvaluator:用户自定义属性值接口;
TypeEvaluator的子类:
IntEvaluator:整数属性值。
FloatEvaluator:浮点数属性值。
ArgbEvaluator:十六进制color属性值。
对象属性非以上三类,需自定义TypeEvaluator:
public class FloatEvaluator implements TypeEvaluator<float[]> {
@Override
public float[] evaluate(float fraction, float[] startValue,
float[] endValue)
{
//实现自定义规则计算的float[]类型的属性值
float[] temp = new float[2];
temp[0] = fraction * 2;
temp[1] = (float)Math.random() * 10 * fraction;
return temp;
}
}
7. 属性动画拓展之ViewPropertyAnimator动画
在Android API 12时,View中添加了animate方法
public class View implements Drawable.Callback, KeyEvent.Callback,
AccessibilityEventSource {
......
/**
* This method returns a ViewPropertyAnimator object, which can be used to animate
* specific properties on this View.
*
* @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
*/
public ViewPropertyAnimator animate() {
if (mAnimator == null) {
mAnimator = new ViewPropertyAnimator(this);
}
return mAnimator;
}
......
}
可以看见通过View的animate()方法可以得到一个ViewPropertyAnimator的属性动画(有人说他没有继承Animator类,是的,他是成员关系,不是之前那种继承关系)。
ViewPropertyAnimator提供了一种非常方便的方法为View的部分属性设置动画(切记,是部分属性),它可以直接使用一个 Animator对象设置多个属性的动画;在多属性设置动画时,它比 上面的ObjectAnimator更加牛逼、高效,因为他会管理多个属性的invalidate方法统一调运触发,而不像上面分别调用,所以还会有一些 性能优化。如下就是一个例子:
myView.animate().x(0f).y(100f).start();
8. 属性动画拓展之LayoutAnimator容器布局动画
Property动画系统还提供了对ViewGroup中View添加时的动画功能,我们可以用LayoutTransition对 ViewGroup中的View进行动画设置显示。该类用于当前布局容器中有View添加、删除、隐藏、显示等时候定义布局容器自身的动画和View的动画;
一共五种变化类型:
- LayoutTransition.APPEARING:当View出现或者添加的时候View出现的动画。
- LayoutTransition.CHANGE_APPEARING:当添加View导致布局容器改变的时候整个布局容器的动画。
- LayoutTransition.DISAPPEARING:当View消失或者隐藏的时候View消失的动画。
- LayoutTransition.CHANGE_DISAPPEARING:当删除或者隐藏View导致布局容器改变的时候整个布局容器的动画。
- LayoutTransition.CHANGE:当不是由于View出现或消失造成对其他View位置造成改变的时候整个布局容器的动画。
9. 如果属性没有get,set方法解决办法
- 给对象加上set和get方法,如果有权限;
- 用一个类来包装原始对象,增加get,set方法;
- 采用ValueAnimator,监听动画,自己实现属性改变;
10. 属性动画监听器
public static interface AnimatorListener {
void onAnimationStart(Animator animation);
void onAnimationEnd(Animator animation);
void onAnimationCancel(Animator animation);
void onAnimationRepeat(Animator animation);
}
public static interface AnimatorUpdateListener {
void onAnimationUpdate(ValueAnimator animation);
}
五、使用动画注意事项
1、OOM问题(主要针对帧动画图片过大)
2、内存泄漏(无限循环动画退出Activity未停止)
3、兼容性问题
4、View动画的问题
5、不要使用px
6、动画元素的交互
7、硬件加速
六、其他动画
1、CircularReveral
这是Android5.0推出的新的动画框架,可以给View做一个揭露效果
当您显示或隐藏一组 UI 元素时,揭露动画可为用户提供视觉连续性。ViewAnimationUtils.createCircularReveal(View, int, int, float, float))方法让您能够为裁剪区域添加动画以揭露或隐藏视图。五个参数分别是View,中心点坐标,开始半径,结束半径。通过这五个参数的配合,我们可以做出很多不同的效果。
//参数 View,中心点坐标,开始半径,结束半径
Animator animator = ViewAnimationUtils.createCircularReveal(ivOval, ivOval.getWidth() / 2,ivOval.getHeight() / 2, 0, ivOval.getWidth());
animator.setDuration(2000);
animator.start();
2、转场动画
Android 5.0新增了4种转场动画,分别是Explode、Slide、Fade、Share。传统的转场动画只能作用于整个页面,不能对页面中的单个元素做控制,而5.0新转场动画可以控制页面中的每个元素。
Explode: 下一个页面的元素从四面八方进入,最终形成完整的页面
Slide: 下一个页面元素从底部依次向上运动,最终形成完整的页面
Fade: 下一个页面元素渐变出现,最终形成完整的页面
Share: 在跳转的两个Activity之间,如果有相同的View元素,那么,两个元素就可以设置成共享状态,在跳转时,这个View就会从第一个Activity的显示状态过渡到第二个Activity的显示状态,给用户的感觉仿佛是两个Activity共享一个View.
3、矢量动画
矢量图不同于位图是用像素描述图像的,它是用数学曲线描述图形。所以一张图片就是对应着一系列的数学曲线,所以图片的显示尺寸和图片体积无关。它的体积就是文本文件的大小。并且矢量图可以无限拉伸不失真。SVG就是标准的矢量图格式,Android中使用矢量图虽然没有直接使用SVG图片,但是Google提供了一个<vector>标签用来创建VectorDrawable矢量对象,我们只要把svg的path标签中的字符串复制到的path标签中,就能创建出一个一模一样的矢量图形。在AndroidStudio中可以通过导入SVG来在drawable 文件夹下生成相应的矢量图xml 文件进行引用,同时AndroidStudio本身也提供一些矢量图库供开发者使用。除了AndroidStudio本身提供的库,开发者也可以去阿里巴巴矢量图标库去搜寻下载自己想要的矢量图标。打开SVG文件或者vector 标签,我们可以看到path标签中的一串数字,这其实就是用来绘制svg图像,而path标签中那些M、C、Z等命令其实就是绘制svg图像时的规则,我们来看看svg图像各个命令的意思:
M = moveto 相当于 android Path 里的moveTo(),用于移动起始点
L = lineto 相当于 android Path 里的lineTo(),用于画线
H = horizontal lineto 用于画水平线
V = vertical lineto 用于画竖直线
C = curveto 相当于cubicTo(),三次贝塞尔曲线
S = smooth curveto 同样三次贝塞尔曲线,更平滑
Q = quadratic Belzier curve quadTo(),二次贝塞尔曲线
T = smooth quadratic Belzier curveto 同样二次贝塞尔曲线,更平滑
A = elliptical Arc 相当于arcTo(),用于画弧
Z = closepath 相当于closeTo(),关闭path
简单介绍了下Android 下的矢量图,我们继续讲矢量动画。Android中的矢量动画看似很繁杂,其实很简单,就三个类:vector、animated-vector、animated-selector
(1)vector:显示一个矢量图形,用SVG的语法构建path
(2)animated-vector:组合两个vector,让vector动起来
(3)animated-selector:组合两个animated-vector,实现双向切换动画
三个类的递进关系很明显。
参考:(矢量动画具体代码)[https://blog.csdn.net/javaSXL/article/details/80950174]
网友评论