Android动画知识汇总
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android动画知识汇总相关的知识,希望对你有一定的参考价值。
本文是对android动画的汇总。关于Android的动画包括 3.0之前的View Animation,3.0之后的 Property Animator 以及5.0新增的(Touch feedback(触摸反馈)Reveal effect(揭露效果)Activity transitions(Activity转换效果)Curved motion(曲线运动)View state changes (视图状态改变)Animate Vector Drawables(可绘矢量动画))6种动画。
几种动画的详细内容如下:
1. View Animation :
第一类是Tween动画,就是对场景里的对象不断的进行图像变化来产生动画效果。
第二类就是 Frame动画,即顺序的播放事先做好的图像,与gif图片原理类似。
下面就讲一下Tweene Animations。
主要类:
Animation 动画
AlphaAnimation 渐变透明度
otateAnimation 画面旋转
ScaleAnimation 渐变尺寸缩放
ranslateAnimation 位置移动
AnimationSet 动画集
以自定义View为例,该View很简单,画面上只有一个图片。 现在我们要对整个View分别实现各种Tween动画效果。
1) AlphaAnimation实现代码:
//初始化 Animation alphaAnimation = new AlphaAnimation(0.1f, 1.0f); //设置动画时间 alphaAnimation.setDuration(3000); this.startAnimation(alphaAnimation);
其中AlphaAnimation类第一个参数fromAlpha表示动画起始时的透明度, 第二个参数toAlpha表示动画结束时的透明度。setDuration用来设置动画持续时间。
fromAlpha、toAlpha属性说明:0.0表示完全透明 1.0表示完全不透明 以上值取0.0-1.0之间的float数据类型的数字
2) RotateAnimation实现代码:
Animation rotateAnimation = new RotateAnimation(0f, 360f); rotateAnimation.setDuration(1000); this.startAnimation(rotateAnimation);
其中RotateAnimation类第一个参数fromDegrees表示动画起始时的角度, 第二个参数toDegrees表示动画结束时的角度。另外还可以设置伸缩模式pivotXType、pivotYType, 伸缩动画相对于x,y 坐标的开始位置pivotXValue、pivotYValue等 fromDegrees、toDegrees属性值说明:0.0表示收缩到没有 1.0表示正常无伸缩 值小于1.0表示收缩 值大于1.0表示放大。
当角度为负数——表示逆时针旋转
当角度为正数——表示顺时针旋转
(负数from——to正数:顺时针旋转)
(负数from——to负数:逆时针旋转)
(正数from——to正数:顺时针旋转)
(正数from——to负数:逆时针旋转)
pivotX、pivotY属性值说明:从0%-100%中取值,50%为物件的X或Y方向坐标上的中点位置
3) ScaleAnimation实现代码:
//初始化 Animation scaleAnimation = new ScaleAnimation(0.1f, 1.0f,0.1f,1.0f); //设置动画时间 scaleAnimation.setDuration(500); this.startAnimation(scaleAnimation);
ScaleAnimation类中
第一个参数fromX ,第二个参数toX:分别是动画起始、结束时X坐标上的伸缩尺寸。
第三个参数fromY ,第四个参数toY:分别是动画起始、结束时Y坐标上的伸缩尺寸。
另外还可以设置伸缩模式pivotXType、pivotYType, 伸缩动画相对于x,y 坐标的开始位置pivotXValue、pivotYValue等。
4)TranslateAnimation实现代码:
//初始化 nimation translateAnimation = new TranslateAnimation(0.1f, 100.0f,0.1f,100.0f); //设置动画时间 translateAnimation.setDuration(1000); this.startAnimation(translateAnimation);
TranslateAnimation类
第一个参数fromXDelta ,第二个参数toXDelta:分别是动画起始、结束时X坐标。
第三个参数fromYDelta ,第四个参数toYDelta:分别是动画起始、结束时Y坐标。
5)AnimationSet实现代码:
//初始化 Translate动画 translateAnimation = new TranslateAnimation(0.1f, 100.0f,0.1f,100.0f); //初始化 Alpha动画 alphaAnimation = new AlphaAnimation(0.1f, 1.0f); //动画集 AnimationSet set = new AnimationSet(true); set.addAnimation(translateAnimation); set.addAnimation(alphaAnimation); //设置动画时间 (作用到每个动画) set.setDuration(1000); this.startAnimation(set);
6)Interpolator
用于修改一个动画过程中的速率,可以定义各种各样的非线性变化函数,比如加速、减速等。
在Android中所有的插值器都是Interpolator 的子类,通过 android:interpolator 属性你可以引用不同的插值器。下面是几种插值
你可以通过下面的方式使用它们:
<set android:interpolator="@android:anim/accelerate_interpolator"> </set>
自定义插值器
如果你对系统提供的插值器不满意,我们可以创建一个插值器资源修改插值器的属性,比如修改AnticipateInterpolator的加速速率,调整CycleInterpolator的循环次数等。为了完成这种需求,我们需要创建XML资源文件,然后将其放于/res/anim下,然后再动画元素中引用即可。我们先来看一下几种常见的插值器可调整的属性:
<?xml version="1.0" encoding="utf-8"?>
<InterpolatorName xmlns:android="http://schemas.android.com/apk/res/android"
android:attribute_name="value"
/>
android:factor 浮点值,加速速率,默认为1
android:tension 浮点值,起始点后退的张力、拉力数,默认为2
android:tension 同上 android:extraTension 浮点值,拉力的倍数,默认为1.5(2 * 1.5)
android:cycles int,循环的个数,默认为1
android:factor 浮点值,减速的速率,默认为1
浮点值,超出终点后的张力、拉力,默认为2
比如:res/anim/my_overshoot_interpolator.xml:
<?xml version="1.0" encoding="utf-8"?>
<overshootInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
android:tension="7.0"/>
This animation XML will apply the interpolator:
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@anim/my_overshoot_interpolator"
android:fromXScale="1.0"
android:toXScale="3.0"
android:fromYScale="1.0"
android:toYScale="3.0
android:pivotX="50%"
android:pivotY="50%"
android:duration="700" />
如果简单的修改插值器的属性值还不能够满足我们的需求,那么就自己来通过实现Interpolator接口来定义自己的插值器了因为上面所有的Interpolator都实现了Interpolator接口,这个接口定义了一个方法:float getInterpolation(float input);此方法由系统调用,input代表动画的时间,在0和1之间,也就是开始和结束之间。
线性(匀速)插值器定义如下:
public float getInterpolation(float input) { return input; }
加速减速插值器定义如下:
public float getInterpolation(float input) { return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f; }
2.PropertyAnimator动画
Property Animation动画有两个步聚:
a.计算属性值
b.为目标对象的属性设置属性值,即应用和刷新动画
1) 计算属性值
过程一:计算已完成动画分数 elapsed fraction
为了执行一个动画,你需要创建一个ValueAnimator,并且指定目标对象属性的开始、结束值和持续时间。在调用start后的整个动画过程中, ValueAnimator会根据已经完成的动画时间计算得到一个0到1之间的分数,代表该动画的已完成动画百分比。0表示0%,1表示100%。
过程二:计算插值(动画变化率)interpolated fraction
当ValueAnimator计算完已完成动画分数后,它会调用当前设置的TimeInterpolator,去计算得到一个interpolated(插值)分数,在计算过程中,已完成动画百分比会被加入到新的插值计算中。
过程三:计算属性值
当插值分数计算完成后,ValueAnimator 会根据插值分数调用合适的 TypeEvaluator去计算运动中的属性值。
以上分析引入了两个概念:已完成动画分数(elapsed fraction)、插值分数( interpolated fraction )。
核心类:
a. Evaluators
Evaluators 告诉属性动画系统如何去计算一个属性值。它们通过Animator提供的动画的起始和结束值去计算一个动画的属性值。
属性系统提供了以下几种Evaluators:
1.IntEvaluator
2.FloatEvaluator
3.ArgbEvaluator
这三个由系统提供,分别用于计算int,float,color型(十六进制)属性的计算器
b.TypeEvaluator
一个用于用户自定义计算器的接口,如果你的对象属性值类型,不是int,float,或者color类型,你必须实现这个接口,去定义自己的数据类型。TypeEvaluator接口只有一个方法,就是evaluate()方法,它允许你使用的animator返回一个当前动画点的属性值。
c.ValueAnimator
属性动画中的主要的时序引擎,如动画时间,开始、结束属性值,相应时间属性值计算方法等。包含了所有计算动画值的核心函数。也包含了每一个动画时间上的细节,信息,一个动画是否重复,是否监听更新事件等,并且还可以设置自定义的计算类型。
使用ValueAnimator实现动画需要手动更新:
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();
d.ObjectAnimator
继承自ValueAnimator,允许你指定要进行动画的对象以及该对象的一个属性。该类会根据计算得到的新值自动更新属性。ObjectAnimator的自动更新功能,依赖于属性身上的setter和getter方法,所以为了让ObjectAnimator能够正确的更新属性值,你必须遵从以下规范:
1. 该对象的属性必须有get和set方法(方法的格式必须是驼峰式),方法格式为set(),因为ObjectAnimator会自动更新属性,它必须能够访问到属性的setter方法,比如属性名为foo,你就需要一个setFoo()方法,如果setter方法不存在,你有三种选择:
a.添加setter方法
b.使用包装类。通过该包装类通过一个有效的setter方法获取或者改变属性值的方法,然后应用于原始对象,比如NOA的AnimatorProxy。
c.使用ValueAnimator代替
(这3点的意思总结起来就是一定要有一个setter方法,让ObjectAnimator能够访问到)
如果你为ObjectAnimator的工厂方法的可变参数只传递了一个值,那么会被作为动画的结束值。
e. AnimatorSet
提供组合动画能力的类。并可设置组中动画的时序关系,如同时播放、有序播放或延迟播放。Elevator会告诉属性动画系统如何计算一个属性的值,它们会从Animator类中获取时序数据,比如开始和结束值,并依据这些数据计算动画的属性值。
f.ViewPropertyAnimator
可以方便的为某个View的多个属性添加并行的动画,只使用一个ViewPropertyAnimator对象就可以完成。它的行为更像一个ObjectAnimator,因为它修改的是对象的实际属性值。但它为一次性给多个属性添加动画提供了方便,而且使用ViewPropertyAnimator的代码更连贯更易读。
下面的代码段分别展示了使用多个ObjectAnimator对象、一个ObjectAnimator对象、 ViewPropertyAnimator同时为一个View的X和Y属性添加动画的示例:
多个ObjectAnimator结合AnimatorSet实现
ObjectAnimator animX = ObjectAnimator.ofFloat(myView, "x", 50f); ObjectAnimator animY = ObjectAnimator.ofFloat(myView, "y", 100f); AnimatorSet animSetXY = new AnimatorSet(); animSetXY.playTogether(animX, animY); animSetXY.start();
一个ObjectAnimator结合多个PropertyValuesHolder实现
ropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x", 50f); PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 100f); ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvyY).start();
ViewPropertyAnimator: 只需一行代码
myView.animate().x(50f).y(100f);//myView.animate()直接返回一个ViewPropertyAnimator对象
g.PropertyValuesHolder
顾名思义,该类持有属性,相关属性值的操作以及属性的setter,getter方法的创建,属性值以Keyframe来承载,最终由KeyframeSet统一处理。
h.KeyFrame
一个keyframe对象由一对 time / value的键值对组成,可以为动画定义某一特定时间的特定状态。每个keyframe可以拥有自己的插值器,用于控制前一帧和当前帧的时间间隔间内的动画。
Keyframe.ofFloat(0f,0f);
第一个参数为:要执行该帧动画的时间节点(elapsed time / duration)
第二个参数为属性值。
因此如果你想指定某一特定时间的特定状态,那么简单的使用ObjectAnimator就满足不了你了,因为ObjectAnimator.ofInt(....)类似的工厂方法,无法指定特定的时间点的状态。
每个KeyFrame其实也有个Interpolator。如果没有设置,默认是线性的。之前为Animator设置的Interpolator是整个动画的,而系统允许你为每一KeyFrame的单独定义Interpolator,系统这样做的目的是允许你在某一个keyFrame做特殊的处理,也就是整体上是按照你的插值函数来计算,但是,如果你希望某个或某些KeyFrame会有不同的动画表现,那么你可以为这个keyFrame设置Interpolator。因此,Keyframe的定制性更高,你如果想精确控制某一个时间点的动画值及其运动规律,你可以自己创建特定的Keyframe 。
Keyframe使用
为了实例化一个keyframe对象,你必须使用某一个工厂方法:ofInt(), ofFloat(), or ofObject() 去获取合适的keyframe类型,然后你调用ofKeyframe工厂方法去获取一个PropertyValuesHolder对象,一旦你拥有了该对象,你可以将PropertyValuesHolder作为参数获取一个Animator,如下:
Keyframe kf0 = Keyframe.ofFloat(0f, 0f); Keyframe kf1 = Keyframe.ofFloat(.5f, 360f); Keyframe kf2 = Keyframe.ofFloat(1f, 0f); PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2);//动画属性名,可变参数 ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation) rotationAnim.setDuration(5000);
i. KeyFrameSet
根据Animator传入的值,为当前动画创建一个特定类型的KeyFrame集合。
通常通过ObjectAnimator.ofFloat(…)进行赋值时,这些值其实是通过一个KeyFrameSet来维护的
比如:
ObjectAnimator.ofFloat(target, "translateX", 50, 100, 200);
调用者传入的values 为 50,100,200,则numKeyframs = 3,那么创建出相应的Keyframe为:
Keyframe(0,50),Keyframe(1/2,100),Keyframe(1,200), 时间点 0,1/2,1 都是按比例划分的
public static KeyframeSet ofFloat(float... values) { int numKeyframes = values.length; FloatKeyframe keyframes[] = new FloatKeyframe[Math.max(numKeyframes,2)]; if (numKeyframes == 1) { keyframes[0] = (FloatKeyframe) Keyframe.ofFloat(0f); keyframes[1] = (FloatKeyframe) Keyframe.ofFloat(1f, values[0]); } else { keyframes[0] = (FloatKeyframe) Keyframe.ofFloat(0f, values[0]); for (int i = 1; i < numKeyframes; ++i) { keyframes[i] = (FloatKeyframe) Keyframe.ofFloat((float) i / (numKeyframes - 1), values[i]);//这里是关键 } } return new FloatKeyframeSet(keyframes);
2) 在XML中声明属性动画
通过在XML中定义的动画,可以很方便的在多个Activities中重用而且更容易编辑,复用性强。为了区分新的属性动画,从3.1开始,你应res/animator/下存放属性动画的资源文件,使用animator文件夹是可选的,但是如果你想在Eclipse ADT插件中使用布局编辑工具(ADT 11.0.0+),就必须在res/animator文件夹下存放了,因为ADT只会查找res/animator文件夹下的属性动画资源文件。
属性动画支持的Tag有
ValueAnimator - <animator>
ObjectAnimator - <objectAnimator>
AnimatorSet - <set>
<set android:ordering="sequentially"> <set> <objectAnimator android:propertyName="x" android:duration="500" android:valueTo="400" android:valueType="intType"/> <objectAnimator android:propertyName="y" android:duration="500" android:valueTo="300" android:valueType="intType"/> </set> <objectAnimator android:propertyName="alpha" android:duration="500" android:valueTo="1f"/> </set>
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext, R.anim.property_animator); set.setTarget(myObject); set.start();
目录res/animator/filename.xm
编译后的资源为ValueAnimator, ObjectAnimator, or AnimatorSet
XML文件的根元素必须为<set>,<objectAnimator>, or <valueAnimator>之一。也可以在一个set中组织不同的动画,包含其它<set>元素,也就是说,可以嵌套。
<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> ... </set> </set>
3.Andriod L的动画
Material Design是Google推出的一个全新的设计语言,它的特点就是拟物扁平化。
在Android L中新增了如下几种动画:
a. Touch feedback(触摸反馈)
b. Reveal effect(揭露效果)
c. Activity transitions(Activity转换效果)
d. Curved motion(曲线运动)
e. View state changes (视图状态改变)
f. Animate Vector Drawables(可绘矢量动画)
详细的内容如下:
1. 触摸反馈:
触摸反馈最具代表性的就是波纹动画,比如当点击按钮时会从点击的位置产生类似于波纹的扩散效果。
1)波纹效果(Ripple):
可以通过如下代码设置波纹的背景:android:background="?android:attr/selectableItemBackground"波纹有边界 android:background="?android:attr/selectableItemBackgroundBorderless"波纹超出边界
具体代码如下:
<Button android:id="@+id/btn_1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/btn_1" android:padding="10px" android:layout_below="@id/touch_feedback_ripple_textview" /> <Button android:id="@+id/btn_2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/btn_2" android:layout_below="@id/btn_1" android:padding="10px" android:background="?android:attr/selectableItemBackground"/> <Button android:id="@+id/btn_3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/btn_3" android:layout_below="@id/btn_2" android:padding="10px" android:background="?android:attr/selectableItemBackgroundBorderless"/>
效果如下:
2)设置颜色
我们也可以通过设置xml属性来调节动画颜色,从而可以适应不同的主题:
android:colorControlHighlight:设置波纹颜色
android:colorAccent:设置checkbox等控件的选中颜色
2. Circular Reveal:
使用方法:
应用ViewAnimationUtils.createCircularReveal()方法可以去创建一个RevealAnimator动画 。
ViewAnimationUtils.createCircularReveal源码如下:
public static Animator createCircularReveal(View view,nt centerX, int centerY, float startRadius, float endRadius) { return new RevealAnimator(view, centerX, centerY, startRadius, endRadius); }
源码非常简单,就是通过createCircularReveal方法根据5个参数来创建一个RevealAnimator动画对象。
这五个参数分别是:
view 操作的视图
centerX 动画开始的中心点X
centerY 动画开始的中心点Y
startRadius 动画开始半径
startRadius 动画结束半径
实例代码:
final View oval = this.findViewById(R.id.oval); oval.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Animator animator = ViewAnimationUtils.createCircularReveal( oval,oval.getWidth()/2,oval.getHeight()/2,oval.getWidth(),0); animator.setInterpolator(new AccelerateDecelerateInterpolator()); animator.setDuration(2000); animator.start(); } }); final View rect = this.findViewById(R.id.rect); rect.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Animator animator = ViewAnimationUtils.createCircularReveal( rect,0,0,0,(float) Math.hypot(rect.getWidth(), rect.getHeight())); animator.setInterpolator(new AccelerateInterpolator()); animator.setDuration(2000); animator.start(); } });
显示效果:
3. Activity Transition
1) 什么是Transition?
安卓5.0中Activity和Fragment 变换是建立在名叫Transitions的安卓新特性之上的。这个诞生于4.4的transition框架为在不同的UI状态之间产生动画效果提供了非常方便的API。该框架主要基于两个概念:场景(scenes)和变换(transitions)。场景(scenes)定义了当前的UI状态,变换(transitions)则定义了在不同场景之间动画变化的过程。虽然transition翻译为变换似乎很确切,但是总觉得还是没有直接使用transition直观,为了更好的理解下面个别地方直接用transition代表变换。
当一个场景改变的时候,transition主要负责:
(1)捕捉每个View在开始场景和结束场景时的状态。
(2)根据两个场景(开始和结束)之间的区别创建一个Animator。
2) Android 5.0(API 级别 21)支持这些进入与退出转换:
(1)分解 - 从场景中心移入或移出视图。
(2)滑动 - 从场景边缘移入或移出视图。
(3)淡入淡出 - 通过调整透明度在场景中增添或移除视图。
3)Android 5.0(API 级别 21)也支持这些共享元素转换:
(1)changeBounds - 为目标视图的布局边界的变化添加动画。
(2) changeClipBounds - 为目标视图的裁剪边界的变化添加动画。
(3)changeTransform - 为目标视图的缩放与旋转变化添加动画。
(4)changeImageTransform - 为目标图像的大小与缩放变化添加动画。
4) 实现方式:
(1). xml 实现方式:
res/transition/activity_fade.xml
<?xml version="1.0" encoding="utf-8"?> <fade xmlns:android="http://schemas.android.com/apk/res/" android:duration="1000"/> res/transition/activity_slide.xml <?xml version="1.0" encoding="utf-8"?> <slide xmlns:android="http://schemas.android.com/apk/res/" android:duration="1000"/>
MainActivity.java
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_transition); setupWindowAnimations(); } private void setupWindowAnimations() { Slide slide = TransitionInflater.from(this).inflateTransition(R.transition.activity_slide); getWindow().setExitTransition(slide); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_transition); setupWindowAnimations(); } private void setupWindowAnimations() { Fade fade = TransitionInflater.from(this).inflateTransition(R.transition.activity_fade); getWindow().setEnterTransition(fade); }
(2)代码实现方式:
MainActivity.java
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_transition); setupWindowAnimations(); } private void setupWindowAnimations() { Slide slide = new Slide(); slide.setDuration(1000); getWindow().setExitTransition(slide); }
TransitionActivity.java
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_transition); setupWindowAnimations(); } private void setupWindowAnimations() { Fade fade = new Fade(); fade.setDuration(1000); getWindow().setEnterTransition(fade); }
实例代码:
(1). Styles文件 :
<resources> <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> <!--设置选中的颜色--> <!-- 允许使用transitions --> <item name="android:windowContentTransitions">true</item> <!--是否覆盖执行,其实可以理解成是否同步执行还是顺序执行--> <item name="android:windowAllowEnterTransitionOverlap">false</item> <item name="android:windowAllowReturnTransitionOverlap">false</item> </style> </resources>
(2). MainActivity部分代码:
@Override public void onClick(View v) { ArrayList<Pair<View,String>> arrayList = new ArrayList<Pair<View,String>>(); switch (v.getId()) { case R.id.explode_btn: setExplodeTransition(); flag = AnimConstant.EXPLODE_FLAG; break; case R.id.slide_btn: setSlideTransition(); flag = AnimConstant.SLIDE_FLAG; break; case R.id.pade_in_out_btn: setFadeTransition(); flag = AnimConstant.PADE_IN_OUT_FLAG; break; case R.id.shared_element_btn: arrayList.add(new Pair<View, String>(shareElementBtn, "shared_name_btn")); flag = AnimConstant.SHARED_ELEMENTS_FLAG; break; } startActivity(arrayList); } private void setFadeTransition() { Fade fadeTransition = new Fade(); fadeTransition.setDuration(1000); getWindow().setReenterTransition(fadeTransition); getWindow().setExitTransition(fadeTransition); } private void startActivity(ArrayList<Pair<View, String>> arrayList) { Intent intent = new Intent(); intent.setClass(this ,SecondActivity.class); intent.putExtra("transition_flag",flag); ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(this, arrayList.toArray(new Pair[arrayList.size()])); startActivity(intent, options.toBundle()); } private void setExplodeTransition() { Explode explode = new Explode(); explode.setDuration(2000); getWindow().setReenterTransition(explode); getWindow().setExitTransition(explode); } private void setSlideTransition() { Slide slideTransition = new Slide(); slideTransition.setSlideEdge(Gravity.LEFT); slideTransition.setDuration(1000); getWindow().setReenterTransition(slideTransition); getWindow().setExitTransition(slideTransition); }
(3) SecondActivity类:
private Button returnBtn = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); Intent intent = getIntent(); int flag = intent.getIntExtra("transition_flag" ,-1); if (flag != AnimConstant.SHARED_ELEMENTS_FLAG) { setupWindowAnimations(); } returnBtn = (Button) this.findViewById(R.id.return_btn); returnBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { finishAfterTransition(); } }); } private void setupWindowAnimations() { Explode explode = new Explode(); explode.setDuration(2000); getWindow().setEnterTransition(explode); }
显示效果:
4.Curved motion
Material design中的动画利用曲线实现时间内插与空间移动模式。 在 Android 5.0(API 级别 21)及更高版本,您可为动画定义定制时间曲线以及曲线运动模式。PathInterpolator 类别是一个基于贝塞尔曲线或 Path 对象的全新插入器。 此插入器在一个 1x1 的正方形内指定一个运动曲线,定位点位于 (0,0) 以及 (1,1),而控制点则使用构造函数参数指定。
有两种定义PathInterpolator的方法:
第一种XML方式:
<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" android:controlX1="0.4" android:controlY1="0" android:controlX2="1" android:controlY2="1"/>
系统将为材料设计规范中的三种基本曲线提供 XML 资源:
@interpolator/fast_out_linear_in.xml
@interpolator/fast_out_slow_in.xml
@interpolator/linear_out_slow_in.xml
第二种代码实现:
public class SCPahtInterpolator extends PathInterpolator { public static final float DEFALUT_CONTROL_1_X = 0.5f; public static final float DEFALUT_CONTROL_1_Y = 0f; public static final float DEFALUT_CONTROL_2_X = 0f; public static final float DEFALUT_CONTROL_2_Y = 1f; public SCPahtInterpolator() { super(DEFALUT_CONTROL_1_X, DEFALUT_CONTROL_1_Y, DEFALUT_CONTROL_2_X, DEFALUT_CONTROL_2_Y); } public SCPahtInterpolator(Path path) { super(path); } public SCPahtInterpolator(float controlX, float controlY) { super(controlX, controlY); } public SCPahtInterpolator(float controlX1, float controlY1, float controlX2, float controlY2) { super(controlX1, controlY1, controlX2, controlY2); } public SCPahtInterpolator(Context context, AttributeSet attrs) { super(context, attrs); } }
可用Animator.setInterpolator()设置PathInterpolator
ObjectAnimator 类别拥有新的构造函数,可让您一次使用两个或更多属性在路径上为坐标添加动画。 例如,下列动画使用 Path 对象为视图的 X 和 Y 属性添加动画:
ObjectAnimator mAnimator; mAnimator = ObjectAnimator.ofFloat(view, View.X, View.Y, path); ... mAnimator.start();
5.视图状态改变
StateListAnimator 类别让您能够定义视图状态改变时运行的动画。 下列示例显示如何将 StateListAnimator 定义为一个 XML 资源:
<!-- animate the translationZ property of a view when pressed --> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true"> <set> <objectAnimator android:propertyName="translationZ" android:duration="@android:integer/config_shortAnimTime" android:valueTo="2dp" android:valueType="floatType"/> <!-- you could have other objectAnimator elements here for "x" and "y", or other properties --> </set> </item> <item android:state_enabled="true" android:state_pressed="false" android:state_focused="true"> <set> <objectAnimator android:propertyName="translationZ" android:duration="100" android:valueTo="0" android:valueType="floatType"/> </set> </item> </selector>
如果要将定制视图状态动画附加至一个视图,请依照此示例使用 XML 资源文件中的 selector 元素定义一个动画,并使用 android:stateListAnimator属性将此动画分配给您的视图。 如果要将一个状态列表动画分配给您的代码内的一个视图,请使用 AnimationInflater.loadStateListAnimator() 方法,并以 View.setStateListAnimator() 方法将动画分配给您的视图。
当您的主题扩展材料主题时,在默认情况下按钮将拥有一个 Z 动画。如果要避免您的按钮出现这类行为,请将 android:stateListAnimator 属性设置为@null。
AnimatedStateListDrawable 类别让您能够创建图片,显示相关视图之间的状态变化。 Android 5.0 中的某些系统小组件在默认情况下使用这些动画。 下列示例显示如何将 AnimatedStateListDrawable 定义为一个 XML 资源:
<!-- res/drawable/myanimstatedrawable.xml --> <animated-selector xmlns:android="http://schemas.android.com/apk/res/android"> <!-- provide a different drawable for each state--> <item android:id="@+id/pressed" android:drawable="@drawable/drawableP" android:state_pressed="true"/> <item android:id="@+id/focused" android:drawable="@drawable/drawableF" android:state_focused="true"/> <item android:id="@id/default" android:drawable="@drawable/drawableD"/> <!-- specify a transition --> <transition android:fromId="@+id/default" android:toId="@+id/pressed"> <animation-list> <item android:duration="15" android:drawable="@drawable/dt1"/> <item android:duration="15" android:drawable="@drawable/dt2"/> ... </animation-list> </transition> ... </animated-selector>
6.为矢量图片添加动画
矢量图片可在不丢失定义的情况下缩放。 AnimatedVectorDrawable 类别可让您为矢量图片的属性添加动画。
您通常可以在 3 个 XML 文件中定义添加动画的矢量图片:
在 res/drawable/ 中拥有 <vector> 元素的矢量图片
在 res/drawable/ 中拥有 <animated-vector> 元素且已添加动画的矢量图片
在 res/anim/ 中拥有 <objectAnimator> 元素的一个或多个对象动画
添加动画的矢量图片可为 <group> 以及 <path> 元素的属性添加动画。<group> 元素定义路径集或子组,而 <path> 元素则定义将绘制的路径。
当您定义一个您想要添加动画的矢量图片时,请使用 android:name 属性给这些群组和路径指定一个唯一名称,以便让您能够从您的动画定义中引用这些群组或路径。 例如:
<!-- res/drawable/vectordrawable.xml --> <vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="64dp" android:width="64dp" android:viewportHeight="600" android:viewportWidth="600"> <group android:name="rotationGroup" android:pivotX="300.0" android:pivotY="300.0" android:rotation="45.0" > <path android:name="v" android:fillColor="#000000" android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" /> </group> </vector>
已添加动画的矢量图片定义按名称引用矢量图片内的群组和路径:
<!-- res/drawable/animvectordrawable.xml --> <animated-vector xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/vectordrawable" > <target android:name="rotationGroup" android:animation="@anim/rotation" /> <target android:name="v" android:animation="@anim/path_morph" /> </animated-vector>
动画定义代表着 ObjectAnimator 或 AnimatorSet 对象。此示例中的第一个动画将目标群组旋转 360 度:
<!-- res/anim/rotation.xml --> <objectAnimator android:duration="6000" android:propertyName="rotation" android:valueFrom="0" android:valueTo="360" />
此示例中的第二个动画对矢量图片的路径进行变形。 两个路径均需可兼容变形操作:两个路径均需拥有相同数量的指令,而且每个指令均需拥有相同数量的参数。
<!-- res/anim/path_morph.xml --> <set xmlns:android="http://schemas.android.com/apk/res/android"> <objectAnimator android:duration="3000" android:propertyName="pathData" android:valueFrom="M300,70 l 0,-70 70,70 0,0 -70,70z" android:valueTo="M300,70 l 0,-70 70,0 0,140 -70,0 z" android:valueType="pathType" /> </set>
引用的文章:
http://www.open-open.com/lib/view/open1416663769680.html
http://blog.csdn.net/feng88724/article/details/6318430
http://www.lightskystreet.com/2015/05/23/anim_basic_knowledge/
本文出自 “Android - 静心之作” 博客,请务必保留此出处http://6246534.blog.51cto.com/6236534/1860012
以上是关于Android动画知识汇总的主要内容,如果未能解决你的问题,请参考以下文章
Android:将“ViewPager”动画从片段更改为片段