安卓常见动画合集

注:除特殊说明停止维护外,列出的库仍在维护中。长时间未维护的依赖库,提供了jar文件的,可直接依赖jar 文件

谷歌提供

属性动画3.0以上

官方api自带

  • Animators:
1
2
3
ValueAnimator
ObjectAnimator
AnimatorSet
  • Evaluators:
1
2
3
4
IntEvaluator
FloatEvaluator
ArgbEvaluator
TypeEvaluator
  • Interpolators:
1
2
3
4
5
6
7
8
9
10
AccelerateDecelerateInterpolator	
AccelerateInterpolator
AnticipateInterpolator
AnticipateOvershootInterpolator
BounceInterpolator
CycleInterpolator
DecelerateInterpolator
LinearInterpolator
OvershootInterpolator
TimeInterpolator
  • 监听:
1
2
Animator.AnimatorListener
ValueAnimator.AnimatorUpdateListener
  • xml

动画类对应标签
ValueAnimator -> <animator>

ObjectAnimator - <objectAnimator>

AnimatorSet - <set>

代码 使用

  • ValueAnimator

方法:ofInt(), ofFloat(),ofObject()

1
2
3
ValueAnimator animation = ValueAnimator.ofFloat(0f, 100f);
animation.setDuration(1000);
animation.start();
1
2
3
ValueAnimator animation = ValueAnimator.ofObject(new MyTypeEvaluator(), startPropertyValue, endPropertyValue);
animation.setDuration(1000);
animation.start();

使用 ValueAnimator 对象的值

  • 设置AnimatorUpdateListener 监听
1
2
3
4
5
6
7
8
9
10
animation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator updatedAnimation) {
// You can use the animated value in a property that uses the
// same type as the animation. In this case, you can use the
// float value in the translationX property.
float animatedValue = (float)updatedAnimation.getAnimatedValue();
textView.setTranslationX(animatedValue);
}
});
  • ObjectAnimator
1
2
3
ObjectAnimator animation = ObjectAnimator.ofFloat(textView, "translationX", 100f);
animation.setDuration(1000);
animation.start();
1
ObjectAnimator.ofFloat(targetObject, "propName", 1f)
  • AnimatorSet
1
2
3
4
5
6
7
8
9
10
11
AnimatorSet bouncer = new AnimatorSet();
bouncer.play(bounceAnim).before(squashAnim1);
bouncer.play(squashAnim1).with(squashAnim2);
bouncer.play(squashAnim1).with(stretchAnim1);
bouncer.play(squashAnim1).with(stretchAnim2);
bouncer.play(bounceBackAnim).after(stretchAnim2);
ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f);
fadeAnim.setDuration(250);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(bouncer).before(fadeAnim);
animatorSet.start();

监听

  • API:

    Animator.AnimatorListener

    1
    2
    3
    4
    onAnimationStart()
    onAnimationEnd()
    onAnimationRepeat()
    onAnimationCancel()

    ValueAnimator.AnimatorUpdateListener

    1
    2
    onAnimationUpdate()
    getAnimatedValue()
  • 示例:

1
2
3
4
5
6
ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f);
fadeAnim.setDuration(250);
fadeAnim.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator animation) {
balls.remove(((ObjectAnimator)animation).getTarget());
}

ViewGroup

API:

void setAnimator(int transitionType, Animator animator)

transitionType:

1
2
3
4
LayoutTransition.APPEARING 
LayoutTransition.CHANGE_APPEARING
LayoutTransition.DISAPPEARING
LayoutTransition.CHANGE_DISAPPEARING

需Layout布局属性支持:android:animateLayoutchanges= true

View状态动画

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- the pressed state; increase x and y size to 150% -->
<item android:state_pressed="true">
<set>
<objectAnimator android:propertyName="scaleX"
android:duration="@android:integer/config_shortAnimTime"
android:valueTo="1.5"
android:valueType="floatType"/>
<objectAnimator android:propertyName="scaleY"
android:duration="@android:integer/config_shortAnimTime"
android:valueTo="1.5"
android:valueType="floatType"/>
</set>
</item>
<!-- the default, non-pressed state; set x and y size to 100% -->
<item android:state_pressed="false">
<set>
<objectAnimator android:propertyName="scaleX"
android:duration="@android:integer/config_shortAnimTime"
android:valueTo="1"
android:valueType="floatType"/>
<objectAnimator android:propertyName="scaleY"
android:duration="@android:integer/config_shortAnimTime"
android:valueTo="1"
android:valueType="floatType"/>
</set>
</item>
</selector>

布局引用: android:stateListAnimator

1
2
<Button android:stateListAnimator="@xml/animate_scale"
... />

View

API:

1
2
3
4
5
6
translationX,translationY//相对父View
rotation, rotationX, rotationY//相对支点 2D: rotation ,3D旋转
scaleX scaleY //相对支点 2D缩放
pivotX pivotY //控制旋转,缩放支点,默认值为中间
x y //相对父View 最终位置
alpha//View透明度 默认值1,0为完全透明

示例:

创建动画,指定View属性即可

1
ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f);

Interpolator

  • AccelerateDecelerateInterpolator
1
2
3
4

public float getInterpolation(float input) {
return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
}
  • LinearInterpolator
1
2
3
4

public float getInterpolation(float input) {
return input;
}

ViewPropertyAnimator

  • 组合 ObjectAnimator
1
2
3
4
5
6

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
1
2
3
4

PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x", 50f);
PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 100f);
ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvyY).start();
  • ViewPropertyAnimator
1
2

myView.animate().x(50f).y(100f);

xml定义

  • 定义 AnimatorSet

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <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

1
2
3
4
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext,
R.anim.property_animator);
set.setTarget(myObject);
set.start();
  • 定义 Animator
1
2
3
4
5
<animator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:valueType="floatType"
android:valueFrom="0f"
android:valueTo="-100f" />
  • 引入Animator
1
2
3
4
5
6
7
8
9
10
11
ValueAnimator xmlAnimator = (ValueAnimator) AnimatorInflater.loadAnimator(this,
R.animator.animator);
xmlAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator updatedAnimation) {
float animatedValue = (float)updatedAnimation.getAnimatedValue();
textView.setTranslationX(animatedValue);
}
});

xmlAnimator.start();

物理动画

官方支持库support-dynamic-animation

gradle依赖

1
compile 'com.android.support:support-dynamic-animation:27.1.0'

版本:

注:要求sdk最低版本 为16,编译版本27,功能可用情况下,可适当降低support版本及编译版本

api

官方地址

  • 接口
1
2
DynamicAnimation.OnAnimationEndListener
DynamicAnimation.OnAnimationUpdateListener
1
2
3
4
5
6
7
DynamicAnimation<T extends DynamicAnimation<T>>
DynamicAnimation.ViewProperty
FlingAnimation
FloatPropertyCompat<T>
FloatValueHolder
SpringAnimation
SpringForce

使用

开源库

属性动画 3.0以下

NineOldAndroids

注:已停止更新

gradle依赖

1
compile 'com.nineoldandroids:library:2.4.0'

jar 依赖

将jar包:nineoldandroids-2.4.0.jar 置于libs目录

使用

与官方属性动画api使用方式一致

加载动画

ZLoading

源码支持api 15及以上,14及以下需手动变更,功能无影响

gradle依赖
1
compile 'com.zyao89:zloading:1.0.11'
使用
  • xml
1
2
3
4
5
<com.zyao89.view.zloading.ZLoadingView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:z_type="CircleBuilder"
app:z_color="@color/colorAccent"/>
  • 代码:ZLoadingView
1
2
3
ZLoadingView zLoadingView = (ZLoadingView) findViewById(R.id.loadingView_1);
zLoadingView.setLoadingBuilder(Z_TYPE.CIRCLE);//设置类型
zLoadingView.setColorFilter(Color.WHITE);//设置颜色
  • Dialog:ZLoadingDialog
1
2
3
4
5
6
7
ZLoadingDialog dialog = new ZLoadingDialog(MainActivity.this);
dialog.setLoadingBuilder(type)//设置类型
.setLoadingColor(Color.BLACK)//颜色
.setHintText("Loading...")
.setHintTextSize(16) // 设置字体大小 dp
.setHintTextColor(Color.GRAY) // 设置字体颜色
.show();
支持的类型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
类名			  		枚举类型			 名称
CircleBuilder CIRCLE 圆
ClockBuilder CIRCLE_CLOCK 计时器
StarBuilder STAR_LOADING 跳舞的星星
LeafBuilder LEAF_ROTATE 旋转的叶子
DoubleCircleBuilder DOUBLE_CIRCLE 画两个圈圈
PacManBuilder PAC_MAN PacMan
ElasticBallBuilder ELASTIC_BALL 颤抖吧!球球
InfectionBallBuilder INFECTION_BALL 感染体
IntertwineBuilder INTERTWINE 交织
TextBuilder TEXT 文字
SearchPathBuilder SEARCH_PATH 搜索等待
RotateCircleBuilder ROTATE_CIRCLE 多圆旋转
SingleCircleBuilder SINGLE_CIRCLE 单圆简单动画
SnakeCircleBuilder SNAKE_CIRCLE 引蛇出洞
StairsPathBuilder STAIRS_PATH 舞动阶梯
MusicPathBuilder MUSIC_PATH 跳动音符
StairsRectBuilder STAIRS_RECT 递增方块
ChartRectBuilder CHART_RECT 跳动的柱状图
效果

gif

airbnb-lottie-android

支持动画json文件解析,canvas绘制动画

gradle依赖

使用latest.integration依赖最新版本

1
compile 'com.airbnb.android:lottie:latest.integration'
使用
  • xml
1
2
3
4
5
6
7
<com.airbnb.lottie.LottieAnimationView  
android:id="@+id/animation_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:lottie_fileName="hello-world.json"
app:lottie_loop="true"
app:lottie_autoPlay="true" />
  • 代码
1
2
3
4
LottieAnimationView animationView = (LottieAnimationView) findViewById(R.id.animation_view);  
animationView.setAnimation("hello-world.json");
animationView.loop(true);
animationView.playAnimation();

android-gif-drawable

源码编译需ndk支持

Android studio 插件:


支持gif格式,最低支持api版本:14

gradle依赖
1
compile 'pl.droidsonroids.gif:android-gif-drawable:1.2.12'

如果依赖失败,在项目 gradle内配置:

1
2
3
4
5
6
7
8
9
10
buildscript {
repositories {
mavenCentral()
}
}
allprojects {
repositories {
mavenCentral()
}
}
使用示例
  1. xml

ImageView

1
2
3
4
5
6
<pl.droidsonroids.gif.GifImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/src_anim"
android:background="@drawable/bg_anim"
/>

TextView

1
2
3
4
5
6
7
<pl.droidsonroids.gif.GifTextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:drawableTop="@drawable/left_anim"
android:drawableStart="@drawable/left_anim"
android:background="@drawable/bg_anim"
/>
  1. 代码

GifImageViwe, GifImageButton ,GifTextView

支持setImageResource(int resId)setBackgroundResource(int resId)动态设置gif图片资源

GifDrawable:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
//asset file
GifDrawable gifFromAssets = new GifDrawable( getAssets(), "anim.gif" );

//resource (drawable or raw)
GifDrawable gifFromResource = new GifDrawable( getResources(), R.drawable.anim );

//Uri
ContentResolver contentResolver = ... //can be null for file:// Uris
GifDrawable gifFromUri = new GifDrawable( contentResolver, gifUri );

//byte array
byte[] rawGifBytes = ...
GifDrawable gifFromBytes = new GifDrawable( rawGifBytes );

//FileDescriptor
FileDescriptor fd = new RandomAccessFile( "/path/anim.gif", "r" ).getFD();
GifDrawable gifFromFd = new GifDrawable( fd );

//file path
GifDrawable gifFromPath = new GifDrawable( "/path/anim.gif" );

//file
File gifFile = new File(getFilesDir(),"anim.gif");
GifDrawable gifFromFile = new GifDrawable(gifFile);

//AssetFileDescriptor
AssetFileDescriptor afd = getAssets().openFd( "anim.gif" );
GifDrawable gifFromAfd = new GifDrawable( afd );

//InputStream (it must support marking)
InputStream sourceIs = ...
BufferedInputStream bis = new BufferedInputStream( sourceIs, GIF_LENGTH );
GifDrawable gifFromStream = new GifDrawable( bis );

//direct ByteBuffer
ByteBuffer rawGifBytes = ...
GifDrawable gifFromBytes = new GifDrawable( rawGifBytes );
gif控制

MediaController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GifImageButton gib = new GifImageButton(this);
setContentView(gib);
gib.setImageResource(R.drawable.sample);
final MediaController mc = new MediaController(this);
mc.setMediaPlayer((GifDrawable) gib.getDrawable());
mc.setAnchorView(gib);
gib.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mc.show();
}
});
}
1
2
3
4
5
6
7
getLoopCount()//循环次数
getNumberOfFrames()//返回帧数,至少1帧
getComment()// 注释文本
getFrameByteCount()//可用于存储单帧像素最小字节数
getAllocationByteCount()//GifDrawable用于存储像素的已分配内存的大小(以字节为单位)
getInputSourceByteCount()//后备输入数据的长度(字节)
toString()//调试用的,图像大小和帧数的信息
回调

MultiCallback

支持的功能:

recycle() 释放内存

isRecycled()

getError() 返回错误详细内容

1
2
3
4
5
6
7
8
9
MultiCallback multiCallback = new MultiCallback();

imageView.setImageDrawable(gifDrawable);
multiCallback.addView(imageView);

anotherImageView.setImageDrawable(gifDrawable);
multiCallback.addView(anotherImageView);

gifDrawable.setCallback(multiCallback);

物理-弹簧动画

已停止维护,依赖可用

FaceBook-Rebound

Gradle依赖

1
compile 'com.facebook.rebound:rebound:0.3.8'

jar 依赖

将jar包:rebound-0.3.8.jar置于libs目录

API

类: SpringSystem

方法:create

监听:SpringListener ,SimpleSpringListener

回调方法:
onSpringUpdate
onSpringAtRest
onSpringActivate
onSpringEndStateChange

官方使用示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
SpringSystem springSystem = SpringSystem.create();

// Add a spring to the system.
Spring spring = springSystem.createSpring();

// Add a listener to observe the motion of the spring.
spring.addListener(new SimpleSpringListener() {

@Override
public void onSpringUpdate(Spring spring) {
// You can observe the updates in the spring
// state by asking its current value in onSpringUpdate.
float value = (float) spring.getCurrentValue();
float scale = 1f - (value * 0.5f);
targetView.setScaleX(scale);
targetView.setScaleY(scale);
}
});

// Set the spring in motion; moving from 0 to 1
spring.setEndValue(1);

属性-动画View Shaker

AndroidViewAnimations

内置多种动画,支持链式调用

最近更新日期:2017/6

gradle依赖

1
2
compile 'com.daimajia.easing:library:2.0@aar'
compile 'com.daimajia.androidanimations:library:2.3@aar'

API

枚举类型 Techniques,指定具体类型即可

with

palyOn(View target)

使用示例

1
2
3
4
YoYo.with(Techniques.Tada)
.duration(700)
.repeat(5)
.playOn(targetView);
1
YoYo.with(Techniques.Shake).playOn(targetView);

效果

完结撒花