Android动画
2021-05-25 本文已影响0人
展翅高飞鹏程万里
帧动画
帧动画在使用时需要注意什么? | 问题解释或者解决方案 |
---|---|
OOM问题 | 当图片数量较多且图片较大时就容易出现OOM,这个在实际开发中尤其注意,尽量避免使用帧动画。 |
内存泄漏 | 无限循环运行的帧动画,需要在Activity,Fragment,Dialog等对象结束的时候,需要及时停止运行动画 |
例子:
<?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/a_0"
android:duration="100" />
<item
android:drawable="@drawable/a_1"
android:duration="100" />
<item
android:drawable="@drawable/a_2"
android:duration="100" />
</animation-list>
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_frame_animation);
ImageView animationImg1 = (ImageView) findViewById(R.id.animation1);
animationImg1.setImageResource(R.drawable.frame_anim1);
AnimationDrawable animationDrawable1 = (AnimationDrawable) animationImg1.getDrawable();
animationDrawable1.start();
}
android:onshot
值为false,解释为循环执行。值为true,解释为一次执行
View补间动画
View动画问题 | 问题解释或者解决方案 |
---|---|
View状态 | 补间动画只是对View的影像进行操作,并不影响View的实际状态 |
不要使用px | 在进行动画的过程中,要尽量使用dp,使用px会导致在不同的设备上有不同的效果。 |
硬件加速 | 使用动画的过程中,建议开启硬件加速,这样子会提高动画的流畅性 |
在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>
...
</set>
</set>
Animation animation = AnimationUtils.loadAnimation(mContext, R.anim.alpha_anim);
img = (ImageView) findViewById(R.id.img);
img.startAnimation(animation);
Interpolator
主要作用是可以控制动画的变化速率 ,就是动画进行的快慢节奏。
pivot
决定了当前动画执行的参考位置
属性动画
属性动画出现的原因? | -- |
---|---|
Android3.0( API11 )后才提供的一种全新动画模式,出现原因作用于对象限于View,没改变View的属性,动画效果单一 |
-
属性动画
和View补间动画
的区别
View的补间动画在执行之后并未改变View的真实布局属性值。属性动画弥补了View动画的缺陷,当动画的属性变化时,属性动画会刷新屏幕。属性动画改变的是对象的真实属性,而且属性动画不止用于View,还可以用于任何对象
private void RotateAnimation() {
ObjectAnimator anim = ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f);
anim.setDuration(1000);
anim.start();
}
private void AlpahAnimation() {
ObjectAnimator anim = ObjectAnimator.ofFloat(myView, "alpha", 1.0f, 0.8f, 0.6f, 0.4f, 0.2f, 0.0f);
anim.setRepeatCount(-1);
anim.setRepeatMode(ObjectAnimator.REVERSE);
anim.setDuration(2000);
anim.start();
}
ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(myView, "alpha", 1.0f, 0.5f, 0.8f, 1.0f);
ObjectAnimator scaleXAnim = ObjectAnimator.ofFloat(myView, "scaleX", 0.0f, 1.0f);
ObjectAnimator scaleYAnim = ObjectAnimator.ofFloat(myView, "scaleY", 0.0f, 2.0f);
ObjectAnimator rotateAnim = ObjectAnimator.ofFloat(myView, "rotation", 0, 360);
ObjectAnimator transXAnim = ObjectAnimator.ofFloat(myView, "translationX", 100, 400);
ObjectAnimator transYAnim = ObjectAnimator.ofFloat(myView, "tranlsationY", 100, 750);
AnimatorSet set = new AnimatorSet();
set.playTogether(alphaAnim, scaleXAnim, scaleYAnim, rotateAnim, transXAnim, transYAnim);
// set.playSequentially(alphaAnim, scaleXAnim, scaleYAnim, rotateAnim, transXAnim, transYAnim);
set.setDuration(3000);
set.start();
属性动画的原理
属性动画的运行机制是通过不断地对值进行操作来实现的,而初始值和结束值之间的动画过度就是由ValueAnimator这个类来负责计算的。他内部使用一种时间循环的机制计算值与值之间的动画过渡。ValueAnimator还负责管理动画的
播放次数
,播放模式
以及动画设置监听器
等。
因为ValueAnimator可以为任何的对象支持动画操作。那么如何计算startValue到endValue之间的值呢?
ValueAnimator对这种计算过程,抽象成两个层次:
- 总时间与计算过程值(差值)之间的比值,也称为动画的完成度(百分数表示。0%表示还未开始,100%表示动画已经执行完成)
- 根据当前时间点的动画完成度,针对设置的startValue与endValue,动态计算目标对象的当前时间点的属性值。
TimeInterpolator
TimeInterpolator
决定了动画从初始值过渡到结束值的节奏。抽象过程一
public interface TimeIntercepolator {
/**
* input: input A value between 0 and 1.0.表示当前动画时间完成度
* return: 返回值。根据动画时间完成值(客观),二次计算动画时间完成值 (计算:动画的完成度)
*/
float getInterpolation(float input);
}
例子
<!-- DecelerateInterpolator -->
public float getInterpolation(float input) {
float result;
if (mFactor == 1.0f) {
result = (float)(1.0f - (1.0f - input) * (1.0f - input));
} else {
result = (float)(1.0f - Math.pow((1.0f - input), 2 * mFactor));
}
return result;
}
<!--
这里使用了两种函数用来计算动画完成的度:
方式一:y = 1 - (1 - x ) * (1 - x )
方式二:y = 1 - (1 - x)^b
涉及到二次函数的走势问题。可参考连接:https://zuotu.91maths.com/
特别说明:方式二中的b常数。b越大函数的走向越陡峭,说明动画执行速度越快,但是整体的加速度占比变短。因为速度太快了,需要花越多时间减速
-->
<!--AccelerateInterpolator-->
public float getInterpolation(float input) {
if (mFactor == 1.0f) {
return input * input;
} else {
return (float)Math.pow(input, mDoubleFactor);
}
}
<!--
这里使用了两种函数用来计算动画完成的度:
方式一:y = x^2
方式二:y = x^b
涉及到二次函数的走势问题。可参考连接:https://zuotu.91maths.com/
特别说明:方式二中的常数b。b越大,一开始的速度越慢,越慢的这种状态的速度占有越久,到后面加速的时速度越快,但时间越短
-->
TypeEvaluator
TypeEvaluator
决定了动画如何从初始值过渡到结束值。抽象过程二
public interface TypeEvaluator {
/**
* fraction: 表示当前时间点动画完成的百分比。0表示未开始 ,100%表示已经完成
* startValue:设置动画对象属性的初始值
* endValue:设置动画对象的结束值
* /
@Override
public abstract Object evaluate(float fraction, Object startValue,Object endValue);
}
例子一
实现目标对象的属性值(类型为Point)从start变化到end的过程
Point startPoint = (Point) startValue;
Point endPoint = (Point) endValue;
float x = startPoint.getX() + fraction * (endPoint.getX() - startPoint.getX());
float y = (float) (Math.sin(x * Math.PI / 180) * 100) + endPoint.getY() / 2;
Point point = new Point(x, y);
return point;