以前写动画也是零零种种,需要的时候就查API或找现成的,不够系统。现在通过学习将Android整个动画体系勾勒出来,做到有的放矢。
安卓框架提供了2个动画系统:属性动画(Android 3.0)
和View动画
。这两种动画系统都是可行的,但是,在一般情况下,属性动画是首选的方法
,因为它是更灵活,提供更多的功能。除了这两个系统,你可以利用Drawable动画
,它允许你一帧一个的加载显示Drawable资源。所以总体来说Android API提供了三类的动画:
- Tween动画或View动画(API 1.0开始)
- Drawable动画或Frame动画、帧动画
- Property动画:Android 3.0(API 11)以上版本可用,Android推荐。
Android有关动画的类在android.view.animation
包中,抽象类Animation有很多子类,以完成不同的动画效果。
Animation子类 | 动画效果 |
---|---|
AlphaAnimation | 渐变透明度动画效果 |
RotateAnimation | 旋转动画 |
ScaleAnimation | 尺寸缩放动画 |
TranslateAnimation | 位移动画 |
AnimationSet | 动画容器 |
Tween动画结束时View的布局属性并未发生变化
Animation类中有一个内部动画监听类AnimationListener
,通过它主要实现动画开始、进行到结束的事件监听。它有三个方法void onAnimationStart(Animation animation);
、void onAnimationRepeat(Animation animation);
、void onAnimationEnd(Animation animation);
。
在res/anim目录下定义动画文件,然后在代码中AnimationUtilsd.loadAnimation(context,animId)
来调用。
View动画或Tween动画在Android比较老的系统中就有了,它仅适用于View。它也比较容易设置,可以提供足够的能力,以满足许多应用的需求。
Animation通用
属性:xml属性 | Java代码 | 说明 |
---|---|---|
android:duration | setDuration(long) | 动画持续时间,ms为单位 |
android:fillAfter | setFillAfter(boolean) | 动画结束时是否保留在最后状态 |
android:fillBefore | setFillBefore(boolean) | 动画结束时是否还原到初始状态(默认是true) |
android:fillEnabled | setFillEnabled(boolean) | 同android:fillBefore |
android:interpolator | setInterpolator | 设定插值器。& |
android:repeatCount | setRepeatCount(int) | 设置重复次数 |
android:repeatMode | setRepeatMode() | 设置重复模式(reverse |
android:startOffset | setStartOffset | 调用start函数后等待多久后开始 |
android:zAdjustment | setZAdjustment | 设置z轴位置(top |
& 3种插值器:
accelerate_decelerate_interpolator
加速-减速 动画插入器accelerate_interpolator
加速-动画插入器decelerate_interpolator
减速- 动画插入器
XML属性 | Java代码 | 说明 |
---|---|---|
android:fromAlpha | AlphaAnimation(float fromAlpha, float toAlpha) | 动画开始的透明度 |
android:toAlpha | AlphaAnimation(float fromAlpha, float toAlpha) | 动画结束时的透明度 |
<alpha xmlns:android="http://schemas.android.com/apk/res/android" android:fromAlpha="1.0" android:toAlpha="0.1"/>
XML属性 | Java代码 | 说明 |
---|---|---|
android:fromDegrees | RotateAnimation(float fromDegrees, …) | 旋转开始角度,正表示逆时针 |
android:toDegrees | RotateAnimation(…, float toDegrees) | 旋转结束角度,负代表正时针 |
android:pivotX | RotateAnimation(…, …, float pivotX,…) | 旋转起点X坐标,* |
android:pivotY | RotateAnimation(…,…,…, float pivotY) | 旋转起点Y坐标 |
<rotate xmlns:android="http://schemas.android.com/apk/res/android" android:fromDegrees="0" android:pivotX="50%" android:pivotY="50%" android:toDegrees="360" />
XML属性 | Java代码 | 说明 |
---|---|---|
android:fromXScale | ScaleAnimation(float fromX, …) | 初始X轴缩放比例 ,1是不变,0是最小,0~1是缩小,>1是放大。 |
android:toXScale | ScaleAnimation(…, float toX,…) | 结束X轴缩放比例,同上 |
android:fromYScale | ScaleAnimation(…, float fromY,…) | 初始Y轴缩放比例,同上 |
android:toYScale | ScaleAnimation(…, float toY) | 结束Y轴缩放比例,同上 |
android:pivotX | ScaleAnimation(…, float pivotX, …) | 缩放起点X坐标 * |
android:pivotY | ScaleAnimation(…, float pivotY) | 缩放起点Y坐标 * |
<scale xmlns:android="http://schemas.android.com/apk/res/android" android:fromXScale="1.0" android:fromYScale="1.0" android:pivotX="50%" android:pivotY="50%" android:toXScale="0.1" android:toYScale="0.1" />
XML属性 | Java代码 | 说明 |
---|---|---|
android:fromXDelta | ScaleAnimation(float fromX, …) | 初始X轴坐标 * |
android:toXDelta | ScaleAnimation(…, float toX,…) | 结束X轴坐标 * |
android:fromYDelta | ScaleAnimation(…, float fromY,…) | 初始Y轴坐标 * |
android:toYDelta | ScaleAnimation(…, float toY) | 结束Y轴坐标 * |
<translate xmlns:android="http://schemas.android.com/apk/res/android" android:fromXDelta="20%" android:fromYDelta="20%" android:toXDelta="50%" android:toYDelta="50%" />
*数值或百分数,如50表示View的左上角50个像素为起始点,
50%
表示以当前View的左上角加上当前View的50%宽高作为起始点,50%p
表示以当前View的左上角加父控件的50%的宽高为起始点。在XML中可以方便的用%号来表示,那么在代码中,使用pivotType表示,有三种:Animation.ABSOLUTE
,Animation.RELATIVE_TO_SELF
,和Animation.RELATIVE_TO_PARENT
Tween动画是通过
ParentView
来不断调整ChildView
的画布坐标系来实现的。
applyTransformation(float interpolatedTime, Transformation t)
Transformation里面有一个矩阵Matrix,和Alpha。实现自己的动画,也是继承Animation,然后重写applyTransformation
方法。
根据这个原理,定制自己的Tween动画:借助android.graphics.Camera
类。可实现
- 3D翻转动画
- 扭曲动画
- 抛物线
可以通过在XML中定义多个动画,执行时里面的动画是同时执行
的。
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha/>
<scale/>
<translate/>
<rotate/>
</set>
Drawable动画,也叫帧动画。它对应的操作类在android.graphics.drawable
包下,AnimationDrawable
类。有XML方式和Java代码两种方式。
它的属性如下:
属性(方法) | 方法 |
---|---|
start() | 开始播放 |
stop() | 通知播放 |
addFrame(Drawable frame,int duration) | 添加一帧,并设置持续时间 |
getDuration(int index) | 得到指定帧的持续时间 |
getFrame(int index) | 得到指定帧的drawable |
getNumberOfFrames() | 得到所有帧的数量 |
isOneShot() | 是否执行一次 |
isRunning() | 是否正在播放 |
setOneShot(boolean oneShot) | 设置是否执行一次 |
注意:
start()
方法不能再Activity的onCreate()
中调用,因为那时AnimationDrawable
还未完全附着在Window
上。如果想最快的运行,可在onWindowFocusChange()
方法中调用。
XML中设置:
<animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false">
<item android:drawable="@mipmap/common_loading3_0" android:duration="50"/>
<item android:drawable="@mipmap/common_loading3_1" android:duration="50"/>
<item android:drawable="@mipmap/common_loading3_2" android:duration="50"/>
<item android:drawable="@mipmap/common_loading3_3" android:duration="50"/>
<item android:drawable="@mipmap/common_loading3_4" android:duration="50"/>
<item android:drawable="@mipmap/common_loading3_5" android:duration="50"/>
<item android:drawable="@mipmap/common_loading3_6" android:duration="50"/>
<item android:drawable="@mipmap/common_loading3_7" android:duration="50"/>
<item android:drawable="@mipmap/common_loading3_8" android:duration="50"/>
<item android:drawable="@mipmap/common_loading3_9" android:duration="50"/>
<item android:drawable="@mipmap/common_loading3_10" android:duration="50"/>
<item android:drawable="@mipmap/common_loading3_11" android:duration="50"/>
</animation-list>
Java中设置:
@TargetApi(16)
AnimationDrawable animationDrawable = new AnimationDrawable();
Resources r = getResources();
animationDrawable.addFrame(r.getDrawable(R.mipmap.common_loading4_0), 50);
animationDrawable.addFrame(r.getDrawable(R.mipmap.common_loading4_1), 50);
animationDrawable.addFrame(r.getDrawable(R.mipmap.common_loading4_2), 50);
animationDrawable.addFrame(r.getDrawable(R.mipmap.common_loading4_3), 50);
animationDrawable.addFrame(r.getDrawable(R.mipmap.common_loading4_4), 50);
animationDrawable.addFrame(r.getDrawable(R.mipmap.common_loading4_5), 50);
animationDrawable.addFrame(r.getDrawable(R.mipmap.common_loading4_6), 50);
animationDrawable.addFrame(r.getDrawable(R.mipmap.common_loading4_7), 50);
animationDrawable.addFrame(r.getDrawable(R.mipmap.common_loading4_8), 50);
animationDrawable.addFrame(r.getDrawable(R.mipmap.common_loading4_9), 50);
animationDrawable.addFrame(r.getDrawable(R.mipmap.common_loading4_10), 50);
animationDrawable.addFrame(r.getDrawable(R.mipmap.common_loading4_11), 50);
animationDrawable.setOneShot(false);
if(Build.VERSION.SDK_INT <= 16){
ivAnimDrawableJava.setBackgroundDrawable(animationDrawable);
}else{
ivAnimDrawableJava.setBackground(animationDrawable);
}
animationDrawable.start();
另一种AnimtionDrawable,很方便让一个Drawable不停的旋转。
<animated-rotate xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/vector_drawable" android:pivotX="50%" android:pivotY="50%" android:visible="true"/>
Interpolator
是一个接口,继承TimeInterpolator
接口,TimeInterpolator只有一个抽象方法需要实现:float getInterpolation(float input)
。Android系统提供了很多内置的一些插值器,比如:
- AccelerateInterpolator:动画从开始到结束,变化率是一个加速的过程。
- DecelerateInterpolator:动画从开始到结束,变化率是一个减速的过程。
- CycleInterpolator:动画从开始到结束,变化率是循环给定次数的正弦曲线。
- AccelerateDecelerateInterpolator:动画从开始到结束,变化率是先加速后减速的过程。
- LinearInterpolator:动画从开始到结束,变化率是线性变化。
LinearInterpolator
线形插值器的源码如下:
@HasNativeInterpolator
public class LinearInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {
public LinearInterpolator() {
}
public LinearInterpolator(Context context, AttributeSet attrs) {
}
public float getInterpolation(float input) {
return input;
}
/** @hide */
@Override
public long createNativeInterpolator() {
return NativeInterpolatorFactoryHelper.createLinearInterpolator();
}
插补器的原理就是通过改变实际执行动画的时间点,提前/延迟执行默认的时间点来达到加速/减速的效果。在getInterpolation
方法中直接返回input(0.0~1.0f)
之间的一个值。input表示正常执行动画的时间点,返回值是用户真正想要它执行的时间点,LinearInterpolator
返回input,他们的斜率(比值)是个常数,所以表示匀速,速率不变。我们可以通过在里面设置函数改变动画的速率。如加速插值器里的getInterpolation
方法是这样实现的:具体分析参考:详解之android动画interpolator插补器。
public float getInterpolation(float input) {
if (mFactor == 1.0f) {
return input * input;
} else {
return (float)Math.pow(input, mDoubleFactor);
}
}
我们自定义Interpolator也是这样实现,继承BaseInterpolator
,实现getInterpolation
方法,在getInterpolation方法中实现自己的插值函数,做出想要的动画效果。
Android 里的 Property 动画是为了弥补之前 View 动画的不足而在 API 11
之后引入系统的。Property 动画功能非常强大和灵活,学好、用好 Property 动画将对 App 开发带来很好的效果。
Property动画
本质是修改对象属性值实现的动画。在2.3以前的版本中,可以使用NineOldAndroids框架,实现属性动画。
在android.animation包下,抽象类Animator是所有属性动画的超类。
有两个重要的类:
- Keyframe
:fraction(时间)、value(具体值)、interpolator(插值器)。
- PropertyValueHolder
:Property(x位置…)、Keyframe集合。
Animator:
XML属性 | Java代码 | 说明 |
---|---|---|
android:duration | setDuration(long duration) | 动画时长 |
android:interpolator | setInterpolator(TimeIntepolator v) | 插值器 |
android:startOffset | setStartDelay(long delay) | 调用start方法后动画延迟时间 |
setTartget(Object o) | 动画对象 |
ValueAnimator:
XML属性 | Java代码 | 说明 |
---|---|---|
android:repeatMode | setRepeatMode(int value) | 重复模式 |
android:repeatCount | setRepeatCount(int count) | 重复次数 |
android:valueFrom,\nandroid:valueTo,\nandroid:valueType | ofArgb(int..),\nofint(int …) ,\nofFloat(float…) | float,int或color类型,\nfloat,int或color类型,\nintType或floatType,color不用指定 |
setFrameDelay(long delay) | 多长时间刷新一次 |
ObejctAnimator
XML属性 | Java代码 | 说明 |
---|---|---|
android:propertyName | setPropertyName() | String类型,必须要设置的节点属性 |
注意:动画更新的过程中会不断更新该属性,所以对象比较提供该属性的处理方法(getXXX,setXXX)。
属性:x,y,rotateX,rotateY,traslateX,translateY,alpha,scaleX,scaleY
Property动画的原点在对象父容器的0,0位置
AnimationSet
XML属性 | Java代码 | 说明 |
---|---|---|
android:ordering | playSequentially()/playTogether() | 子动画是先后有序的还是同时进行。 |
在res/animator
目录下定义xml(TimeAnimator
不支持),然后使用AnimatorInfaltor.loadAnimator(context,animId)。
res/animator/object_set.xml:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="sequentially">
<!-- set中可以嵌套set,先執行這個set中同時执行的动画 -->
<set android:ordering="together">
<objectAnimator android:duration="1000" android:propertyName="x" android:valueFrom="0" android:valueTo="250" android:valueType="floatType" />
<objectAnimator android:duration="1000" android:propertyName="y" android:valueFrom="0" android:valueTo="250" android:valueType="floatType" />
<objectAnimator android:duration="1000" android:propertyName="rotation" android:valueFrom="0" android:valueTo="360" />
<objectAnimator android:duration="1000" android:propertyName="rotationX" android:valueFrom="0" android:valueTo="360" />
<objectAnimator android:duration="1000" android:propertyName="rotationY" android:valueFrom="0" android:valueTo="360" />
</set>
<objectAnimator android:duration="1000" android:propertyName="scaleX" android:valueFrom="1" android:valueTo="0.5" /><!-- 如果第一次缩小到0.5,第二次再次缩放就没效果,因为属性改了 -->
<objectAnimator android:duration="1000" android:propertyName="scaleY" android:valueFrom="1" android:valueTo="0.5" />
<objectAnimator android:duration="1000" android:propertyName="alpha" android:valueFrom="1" android:valueTo="0.5" />
</set>
对于在XML中定义的动画,在代码中我们这样来使用:
Animator anim0 = AnimatorInflater.loadAnimator(context,R.animator.object_set);
anim0.setTarget(imageView);
anim0.start();
我们也可以自己写ObjectAnimator来实现属性动画:
//如果只写valueTo,则valueFrom表示当前的值
//创建了两个ObjectAnimator,两个动画同时执行
ObjectAnimator.ofFloat(imageView,"rotationX",0f,360f).setDuration(500).start();
ObjectAnimator.ofFloat(imageView,"rotationY",0f,360f).setDuration(500).start();
上面一个ObjectAnimator只修改一个属性,我们还可以让一个ObjectAnimator同时修改多个属性,使用PropertyValuesHolder
:
//一个动画对多个属性进行修改。PropertyValuesHolder对应某一个属性
PropertyValuesHolder x = PropertyValuesHolder.ofFloat("x",0,250);//里面会生成Keyframe的集合
PropertyValuesHolder y = PropertyValuesHolder.ofFloat("y",0,250);
PropertyValuesHolder sx = PropertyValuesHolder.ofFloat("scaleX",1.0f,0.5f);
PropertyValuesHolder sy = PropertyValuesHolder.ofFloat("scaleY",1.0f,0.5f);
PropertyValuesHolder ry = PropertyValuesHolder.ofFloat("rotationY",0,360);
ObjectAnimator.ofPropertyValuesHolder(imageView,x,y,sx,sy,ry).setDuration(3000).start();
我们还可以对其中的关键帧进行设置,比如:
//一个PropertyValuesHolder对应一个Keyframe集合
Keyframe k1 = Keyframe.ofFloat(0,0);//动画开始,第二个参数不关心是哪个属性
k1.setInterpolator(new LinearInterpolator());
Keyframe k2 = Keyframe.ofFloat(0.5f,360);//动画进行到一半了,第二个参数不关心是哪个属性
k2.setInterpolator(new BounceInterpolator());
Keyframe k3 = Keyframe.ofFloat(1.0f,400);//动画完成,第二个参数不关心是哪个属性
k3.setInterpolator(new BounceInterpolator());
//这里在PropertyValuesHolder里设置需要操作的属性
PropertyValuesHolder pvh = PropertyValuesHolder.ofKeyframe("y",k1,k2,k3);
ObjectAnimator.ofPropertyValuesHolder(imageView,pvh).setDuration(2000).start();
如果我们想操作的对象属性,没有set|get方法,那么我们需要操作时,就可以使用ValueAnimator。下面是抛物线下落的 例子(例子不是很好):
//当对象中某属性没有set/get方法时,就不能使用ObjectAnimator来操作属性动画,这时需要ValueAnimator
ValueAnimator valueAnimator = ValueAnimator.ofFloat(1.0f,400f).setDuration(3000);
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.setTarget(imageView);
//每隔10ms就刷新
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
//ValueAnimator本身不对对象属性进行修改,需要自己来处理。这里实现了抛物线下落
float value = (float) animation.getAnimatedValue();
ivPropertyAnim.setX(value);
ivPropertyAnim.setY(0.08f * value * value);
}
});
valueAnimator.start();
Tween动画中我们可以通过applyTransformation(float interpolatedTime, Transformation t)
来自定义动画,也可以通过自定义插值器,覆写getInterpolation
方法来定制动画;前面我们通过addUpdateListener
来定制ValueAnimator
动画,这里我们通过setEvaluator
来定制属性动画。
ObjectAnimator.ofFloat(ivPropertyAnim,"x",0f,360f).setDuration(5000).start();
ObjectAnimator anim1 = ObjectAnimator.ofFloat(ivPropertyAnim,"y",0f,200f).setDuration(5000);
//定制属性动画
anim1.setEvaluator(new TypeEvaluator<Float>() {
@Override
public Float evaluate(float fraction, Float startValue, Float endValue) {
System.out.println("fraction=" + fraction +",start="+startValue+",end="+ endValue);
return startValue * 0.008f * fraction * (endValue - startValue) * fraction * (endValue - startValue);
}
});
anim1.start();
在Android API 12
时,View中有一个animator()
方法,返回ViewPropertyAnimator
对象。
myView.animate().xBy(100).yBy(100).alpha(0.5f).rotation(180);
使用比属性动画更加简单。
布局中有View的添加、删除、显示或隐藏时自身动画和View的动画。
下面的代码在LinearLayout中动态添加一个按钮时,显示一个动画,从0缩放到正常大小的一个动画。
LayoutTransition layoutTransition = new LayoutTransition();
PropertyValuesHolder p1 = PropertyValuesHolder.ofFloat("scaleX",0.0f,1.0f);
PropertyValuesHolder p2 = PropertyValuesHolder.ofFloat("scaleY",0.0f,1.0f);
layoutTransition.setAnimator(LayoutTransition.APPEARING,ObjectAnimator.ofPropertyValuesHolder(btn,p1,p2));
linearLayout.setLayoutTransition(layoutTransition);
linearLayout.addView(btn);
Transition动画
是个动画框架,主要用于场景的切换动画。从Android4.4
引入。Android5.0
中,又将Transition动画
引入到Activity的切换中实现复杂的动画效果。Material Design中,推荐使用Transition动画实现动画和享元切换。已经内建了一些效果,比如Fade,Explode,Slide。Transition动画封装和抽象了属性动画
。
为了提供更加美观一致的 UI 和更好的交互效果,Android 5.0
之后引入了Material Design
,其中它对于动画效果有了新的要求,并也提供了6种新的动画类。
Material Design是一种风格、规范、理念和拟物和扁平设计的结合。Material Design要体现物体的三维大小,材质、轻重、弹性。
触摸反馈。提供了用户与UI交互时可视化的确认接触点。RippleDrawable
类做background,涟漪效果在两种不同的状态间过渡。
物体出现或消失的动画效果。构造方法如下:
ViewAnimationUtils.createCircularReveal(View v, int centerX, int centerY, float startRadius, float endRadius)=>Animator
代码中在点击事件中让一个button显示或消失过程中产生动画:
Animator animator = ViewAnimationUtils.createCircularReveal(
btn,
btn.getWidth() / 2,
btn.getHeight() / 2,
0,
btn.getWidth());
animator.setInterpolator(new LinearInterpolator());
animator.setDuration(6000);
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
btn.setVisibility(View.VISIBLE);
}
});
animator.start();
Activity的过渡动画:进入、退出、共享元素下的进、出
进出支持这些transition效果:Explode、Slide和Fade
共享元素transition效果:changeBounds、changeClipBounds、changeTransform、changeImageTransform
用Activity.finishAfterTransition()
方法,而不是Activity.finish()。
在res/transition目录下,可以添加过渡动画的xml文件:
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
<explode android:duration="2000" />
</transitionSet>
或者
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
<fade android:duration="2000" android:fadingMode="fade_in_out"/>
</transitionSet>
或者
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
<slide android:duration="2000" android:slideEdge="right" />
</transitionSet>
然后在自定义主题中,设置window的进入退出共享元素下的进出动画:在res/values-v21目录下的style中:
<style name="myTheme" parent="android:Theme.Material">
<!-- 允许使用transitions -->
<item name="android:windowContentTransitions">true</item>
<item name="android:windowAllowEnterTransitionOverlap">true</item>
<!-- 指定进入和退出transitions -->
<item name="android:windowEnterTransition">@android:transition/explode</item>
<item name="android:windowExitTransition">@android:transition/explode</item>
<!-- 指定shared element transitions -->
<item name="android:windowSharedElementEnterTransition">
@android:transition/move</item>
<item name="android:windowSharedElementExitTransition">
@android:transition/slide_top</item>
</style>
在Activity的onCreate中设置过渡动画:
@Override
protected void onCreate(Bundle savedInstanceState) {
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
getWindow().setEnterTransition(new Explode().setInterpolator(new BounceInterpolator()).setDuration(2000));
getWindow().setExitTransition(new Fade().setDuration(2000));
getWindow().setReturnTransition(new Slide().setDuration(2000));
getWindow().setReenterTransition(new Slide().setDuration(2000));
getWindow().setSharedElementReenterTransition(new ChangeTransform().setInterpolator(new BounceInterpolator()).setDuration(2000));
super.onCreate(savedInstanceState);
setContentView(R.layout.first3);
}
在startActivity的地方这样做:
case R.id.transition://过渡动画
startActivity(new Intent(First3Effect.this, Second3Effect.class), ActivityOptions.makeSceneTransitionAnimation(this).toBundle());
break;
case R.id.sharetransition://享元模式的过渡动画
View sharedView = findViewById(R.id.p1);
String transitionName = "p1";
ActivityOptions transitionActivityOptions = ActivityOptions.makeSceneTransitionAnimation(First3Effect.this, sharedView, transitionName);
startActivity(new Intent(First3Effect.this, Second3Effect.class), transitionActivityOptions.toBundle());
如果有多个共享元素
// ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this,
// Pair.create(view1, "agreedName1"),
// Pair.create(view2, "agreedName2"));
曲线运动。自定义动画时间曲线和曲线运动模式
PathInterpolator类是一个新的基于贝塞尔曲线路径的插值器
系统提供了三种基本的曲线:
1. @interpolator/fast_out_linear_in.xml
2. @interpolator/fast_out_slow_in.xml
3. @interpolator/linear_out_slow_in.xml
ObjectAnimator.ofFloat(view, View.X, View.Y, path);
StateListAnimator类定义视图状态变化时的动画效果
layout:android:stateListAnimator
AnimationInflater.loadStateListAnimator()
View.setStateListAnimator()
VectorDrawable矢量图片伸缩不失真
AnimatedVectorDrawable矢量图动画
矢量图动画通常包括三类xml文件:
1、<vector>
矢量图,在res/drawable/
2、<animated-vector>
矢量图,在res/drawable/
3、用<objectAnimator>
元素,在res/anim/
本文成自极客学院hexter的学习笔记。