Android动画总结
基础动画
- 平移动画Translation
实现方式一:
xml编写平移动画
base_anim_translation.xml
<?xml version="1.0" encoding="utf-8"?>
<translate
xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="200"
android:toYDelta="200"
android:duration="500"
android:fillAfter="true">
</translate>
代码加载执行动画:
Animation animation = AnimationUtils.loadAnimation(this,R.anim.base_anim_translation);
button.startAnimation(animation);
实现方式二:
TranslateAnimation translateAnimation = new TranslateAnimation(0,200,0,200);
translateAnimation.setDuration(500);//设置执行时间
translateAnimation.setFillAfter(true);
button.startAnimation(translateAnimation);
- 旋转动画Rotation
实现方式一:
xml编写旋转动画
base_anim_rotation.xml
<?xml version="1.0" encoding="utf-8"?>
<rotate
xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="0"
android:toDegrees="90"
android:pivotX="50%"
android:pivotY="50%"
android:duration="500"
android:fillAfter="true">
</rotate>
代码加载执行动画:
Animation animation = AnimationUtils.loadAnimation(this,R.anim.base_anim_rotation);
button.startAnimation(animation);
实现方式二:
RotateAnimation rotateAnimation = new RotateAnimation(0,90,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
rotateAnimation.setDuration(500);
rotateAnimation.setFillAfter(true);
button.startAnimation(rotateAnimation);
- 缩放动画Scale
实现方式一:
xml编写缩放动画
base_anim_scale.xml
<?xml version="1.0" encoding="utf-8"?>
<scale
xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXScale="1"
android:fromYScale="1"
android:toXScale="2"
android:toYScale="2"
android:pivotX="50%"
android:pivotY="50%"
android:duration="500"
android:fillAfter="true">
</scale>
代码加载执行动画:
Animation animation = AnimationUtils.loadAnimation(this,R.anim.base_anim_scale);
button.startAnimation(animation);
实现方式二:
RotateAnimation rotateAnimation = new RotateAnimation(0,90,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
rotateAnimation.setDuration(500);
rotateAnimation.setFillAfter(true);
button.startAnimation(rotateAnimation);
- 透明度动画Alpha
实现方式一:
xml编写透明度动画
base_anim_alpha.xml
<?xml version="1.0" encoding="utf-8"?>
<alpha
xmlns:android="http://schemas.android.com/apk/res/android"
android:fromAlpha="1"
android:toAlpha="0.2"
android:duration="500"
android:fillAfter="true">
</alpha>
代码加载执行动画:
Animation animation = AnimationUtils.loadAnimation(this,R.anim.base_anim_alpha);
button.startAnimation(animation);
实现方式二:
AlphaAnimation alphaAnimation = new AlphaAnimation(1f,0.2f);
alphaAnimation.setDuration(500);
alphaAnimation.setFillAfter(true);
button.startAnimation(alphaAnimation);
- 帧动画
实现方式一:
xml编写帧动画
anim_list.xml
<?xml version="1.0" encoding="utf-8"?>
<animation-list
xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item
android:drawable="@drawable/anim_1"
android:duration="200"/>
<item
android:drawable="@drawable/anim_2"
android:duration="200"/>
<item
android:drawable="@drawable/anim_3"
android:duration="200"/>
<item
android:drawable="@drawable/anim_4"
android:duration="200"/>
</animation-list>
布局:
<ImageView
android:id="@+id/iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
获取背景实现动画:
AnimationDrawable drawable = (AnimationDrawable) iv.getBackground();
if(drawable.isRunning()){
drawable.stop();
}else {
drawable.start();
}
实现方式二:
代码实现方式:
AnimationDrawable animationDrawable = new AnimationDrawable() ;
int[] ids = {R.drawable.anim_1,R.drawable.anim_2,R.drawable.anim_3,R.drawable.anim_4};
//通过循环将每一帧添加到AnimationDrawable中
for(int i = 0 ; i < ids.length ; i ++){
Drawable frame = getResources().getDrawable(ids[i]);
animationDrawable.addFrame(frame,200);
}
animationDrawable.setOneShot(false);
iv.setBackground(animationDrawable);
animationDrawable.start();
属性动画
###ObjectAnimator
- 平移动画
实现方式一:
button.animate().translationX(200).setDuration(500).translationY(200).start();
实现方式二:
ObjectAnimator animator = ObjectAnimator.ofFloat(button,"translationX",200);
animator.setDuration(500);
animator.start();
- 旋转动画
ObjectAnimator animator = ObjectAnimator.ofFloat(button,"rotation",90);
animator.setDuration(500);
animator.start();
- 缩放动画
ObjectAnimator animator = ObjectAnimator.ofFloat(button,"scaleX",2);
animator.setDuration(500);
animator.start();
- 透明度动画
ObjectAnimator animator = ObjectAnimator.ofFloat(button,"alpha",0.2f);
animator.setDuration(500);
animator.start();
- PropertyValuesHolder改变多个属性值
PropertyValuesHolder holder1 = PropertyValuesHolder.ofFloat("translationX",200);
PropertyValuesHolder holder2 = PropertyValuesHolder.ofFloat("translationY",200);
ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(button, holder1, holder2);
animator.setDuration(500);
animator.start();
- 关键帧动画
Keyframe frame1 = Keyframe.ofFloat(0,0);
Keyframe frame2 = Keyframe.ofFloat(0.5f,200);
Keyframe frame3 = Keyframe.ofFloat(1,100);
//将关键帧应用到属性上
PropertyValuesHolder holder = PropertyValuesHolder.ofKeyframe("translationX", frame1, frame2, frame3);
ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(button, holder);
animator.setDuration(500);
animator.start();
- 补间器(差值器)
1、系统自带的补间器
Interpolator | 资源ID | 功能 |
---|---|---|
AccelerateDecelerateInterpolator | @android:anim/accelerate_decelerate_interpolator | 先加速再减速 |
AccelerateInterpolator | @android:anim/accelerate_interpolator | 加速 |
AnticipateInterpolator | @android:anim/anticipate_interpolator | 先后退一小步然后加速前进 |
AnticipateOvershootInterpolator | @android:anim/anticipate_overshoot_interpolator | 先后退一小步再加速前进,超出终点一小步再回到终点 |
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 | 快速到达终点并超出一小步然后回到终点 |
2、平移动画补间器示例
ObjectAnimator animator = ObjectAnimator.ofFloat(button,"translationX", 100,400);
animator.setDuration(500);
//先后退一小步再加速前进,超出终点一小步再回到终点
animator.setInterpolator(new AnticipateOvershootInterpolator());
animator.start();
3、自定义补间器
采用上面创建的ObjectAnimator
animator.setInterpolator(new TimeInterpolator() {
@Override
public float getInterpolation(float input) {
//input 百分比(范围 0 - 1 ) 0.1 0.3 0. 5 只与时间有关
//上面我们定义动画执行时间是500 如果过了200 input=0.4
// 与自己设定的值无关 只与时间有关
Log.i("ObjeceAnimator","interpolation result :"+(1 - input));
return 1 - input;// 1 ---- 0 我们可以根据input自定义返回值
}
});
- Evaluator计算规则
Evaluator是计算规则,系统提供了一些默认的计算规则(FloatEvaluator IntEvaluator)
自定义计算规则
animator.setEvaluator(new TypeEvaluator<Float>() {
@Override
public Float evaluate(float fraction, Float startValue, Float endValue) {
//在这个方法里,我们可以任意的自定义计算规则
float result = startValue + (endValue - startValue) * fraction ;
Log.i("ObjeceAnimator","evaluator fraction:"+fraction+",result:"+result);
return result ;
}
});
- 动画监听
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
float fraction = valueAnimator.getAnimatedFraction();
float value = (float) valueAnimator.getAnimatedValue();
Log.i("ObjeceAnimator","update fraction:"+fraction+",value:"+value);
}
});
Interpolation 中的getInterpolation方法的返回值 负责计算百分比 只和时间有关
Evaluator 中的evaluate方法根据百分比和开始结束值计算value
UpdateListener中的fraction和value都是上面计算的结果
ValueAnimator是动画基础,可以在此基础上完成想要的任何动画
- ValueAnimator
ValueAnimator只提供变化量,并不真正的作用于view上
ValueAnimator根据补间器Interpolator(差值器)时间产生百分比
ValueAnimator根据Evaluator的计算规则和第2步中的百分比,计算value值
ValueAnimator中的UpdateListener监听获取百分比和value
ValueAnimator animator = ValueAnimator.ofFloat(100,200);
animator.setDuration(500);
animator.start();
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float fraction = animation.getAnimatedFraction();
float value = (float) animation.getAnimatedValue();
//在这里设置动画属性
button.setTranslationX(value);
Log.i("ObjectAnimator","fraction:"+fraction+",value:"+value);
}
});
- ValueAnimator.ofObject使用
Evaluator作用:提供计算规则
强调:无论什么类型都需要计算规则Evaluator
ofFloat:系统默认提供FloatEvaluator
ofInt:系统默认提供IntEvaluator
ofObject:系统不知道使用的具体类型,同时又需要计算规则,这时就需要我们自己提供计算规则
ValueAnimator animator = ValueAnimator.ofObject(new CharEvaluator(),new Character('a'),new Character('z'));
animator.setDuration(10000);
animator.start();
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
char value = (char) animation.getAnimatedValue();
button.setText("测试"+value);
}
});
- AnimatorSet
AnimatorSet animatorSet = new AnimatorSet() ;
ObjectAnimator animator1 = ObjectAnimator.ofFloat(testBtn,"translationX",200);
ObjectAnimator animator2 = ObjectAnimator.ofFloat(testBtn,"translationY",200);
animatorSet.play(animator1);
//依次执行动画
animatorSet.playSequentially(animator1,animator2);
//同时执行动画
//animatorSet.playTogether(animator1,animator2);
animatorSet.setDuration(500);
animatorSet.start();
矢量动画
- SVG
1、 SVG Path指令
M = moveto(M X,Y) :将画笔移动到指定的坐标位置
L = lineto(L X,Y) :画直线到指定的坐标位置
H = horizontal lineto(H X):画水平线到指定的X坐标位置
V = vertical lineto(V Y):画垂直线到指定的Y坐标位置
C = curveto(C X1,Y1,X2,Y2,ENDX,ENDY):三次贝赛曲线
S = smooth curveto(S X2,Y2,ENDX,ENDY)
Q = quadratic Belzier curve(Q X,Y,ENDX,ENDY):二次贝赛曲线
T = smooth quadratic Belzier curveto(T ENDX,ENDY):映射
A = elliptical Arc(A RX,RY,XROTATION,FLAG1,FLAG2,X,Y):弧线
Z = closepath():关闭路径
2、 SVG动画示例
1、 定义VectorDrawable
drawable文件夹下定义search_bar.xml
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="150dp"
android:height="24dp"
android:viewportWidth="150"
android:viewportHeight="24">
<!-- 搜索按钮-->
<path
android:name="search"
android:pathData="M141,17 A9,9 0 1,1 142,16 L149,23"
android:strokeWidth="2"
android:strokeColor="#ffffff"
android:strokeAlpha="0.8"
android:strokeLineCap="round" />
<!-- 底部线条 -->
<path
android:name="bar"
android:pathData="M0,23 L149,23"
android:strokeWidth="2"
android:strokeColor="#ffffff"
android:strokeAlpha="0.8"
android:strokeLineCap="square" />
</vector>
2、定义animated-vector
animated-vector相当于一个桥梁,将动画与VectorDrawable连接在一起
drawable文件夹下定义search_to_bar.xml
<?xml version="1.0" encoding="utf-8"?>
<animated-vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/search_bar">
<target
android:animation="@animator/anim_search_none"
android:name="search" />
<target
android:animation="@animator/anim_bar_fill"
android:name="bar" />
</animated-vector>
drawable文件夹下定义bar_to_search.xml
<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/search_bar" >
<!-- animated-vector 相当于是一个桥梁 静态的svg和动画连接的桥梁 -->
<target
android:animation="@animator/anim_search_fill"
android:name="search"/>
<target
android:animation="@animator/anim_bar_none"
android:name="bar"/>
</animated-vector>
3、定义动画
animator文件加下定义anim_bar_fill.xml和anim_bar_none.xml、anim_search_fill.xml、anim_search_none.xml
anim_bar_fill.xml
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator
xmlns:android="http://schemas.android.com/apk/res/android"
android:propertyName="trimPathEnd"
android:valueFrom="0"
android:valueTo="1"
android:valueType="floatType"
android:duration="500" />
anim_bar_none.xml
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator
xmlns:android="http://schemas.android.com/apk/res/android"
android:propertyName="trimPathEnd"
android:valueFrom="1"
android:valueTo="0"
android:valueType="floatType"
android:duration="500" />
anim_search_fill.xml
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500"
android:propertyName="trimPathEnd"
android:valueFrom="0"
android:valueTo="1"
android:valueType="floatType" />
anim_search_none.xml
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator
xmlns:android="http://schemas.android.com/apk/res/android"
android:propertyName="trimPathEnd"
android:valueFrom="1"
android:valueTo="0"
android:valueType="floatType"
android:duration="500" />
4、动画使用
public class SvgActivity extends AppCompatActivity {
private ImageView search ;
private Boolean flag = false ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_svg);
search = (ImageView) findViewById(R.id.search);
final AnimatedVectorDrawable barToSearch = (AnimatedVectorDrawable) getResources().getDrawable(R.drawable.bar_to_search);
final AnimatedVectorDrawable searchToBar = (AnimatedVectorDrawable) getResources().getDrawable(R.drawable.search_to_bar);
search.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(flag) {
search.setImageDrawable(barToSearch);
barToSearch.start();
flag = false ;
}else {
search.setImageDrawable(searchToBar);
searchToBar.start();
flag = true ;
}
}
});
}
}
- 第三方动画框架Lottie
Lottie使用同一个JSON动画文件,可在不同平台实现相同的效果。