1.简述
Android有三种动画,分别是视图动画,属性动画,帧动画。
其中,帧动画因为资源占用大、性能差、内存溢出等不足,实际开发不推荐使用。
2. 插值器 Interpolator
类似物理中的加速度,定义动画进度值变化的速度,默认为线性变化。
android中定义的插值器:
| 插值器 | 功能 |
|---|---|
| AccelerateDecelerateInterpolator | 先加速,后减速 |
| LinearInterpolator | 默认线性,匀速变化,无实际使用 |
| AccelerateInterpolator | 加速运行至结束 |
| DecelerateInterpolator | 减速运行至结束 |
| OvershootInterpolator | 越界折返 |
| AnticipateInterpolator | 先后退一小步再加速 |
| AnticipateOvershootInterpolator | 先后退一小步再加速,超出终点一小部分后再折回 |
| BounceInterpolator | 弹性插值器,篮球落地回弹效果 |
| CycleInterpolator | 周期循环 |
2.1 自定义插值器
通常自定义插值器需实现Interceptor接口
1. 属性动画用的插值器需实现TimeInterpolator接口;
2. 补间动画用的插值器需实现Interpolator
3. Interpolator继承了TimeInterceptor
接口
//input表示进度值0%-100%
public interface TimeInterpolator {
float getInterpolation(float input);
}
public interface Interpolator extends TimeInterpolator {
}
1.自定义插值器
package com.cupster.animation;
import android.view.animation.Interpolator;
class SinInterpolater implements Interpolator {
@Override
public float getInterpolation(float input) {
input = input -0.5f;
return (float)Math.sin(60*input) + 0.5f;
}
}
2.封装使用方法
public static void myAnim(View target ,float... transx){
ObjectAnimator animator = ObjectAnimator.ofFloat(target ,"translationX",transx);
animator.setDuration(3000);
animator.setInterpolator(new SinInterpolater());
animator.start();
}
3.使用
img = findViewById(R.id.anim_view);
img.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
PropAnimatorHelper.myAnim(view ,0,10,0,10);//点击后左右抖动
}
});
4.效果:点击后左右抖动
3.估值器 TypeEvaluator
估值器是定义动画进度值的取值规则。
系统默认的FloatEvaluator、IntEvaluator都是根据进度值自然线性递增。
public class FloatEvaluator implements TypeEvaluator<Number> {
public Float evaluate(float fraction, Number startValue, Number endValue) {
float startFloat = startValue.floatValue();
return startFloat + fraction * (endValue.floatValue() - startFloat);
}
}
举例:0-100的取值范围,就是1,2,3,4,...,99,100
根据使用场景,我们可以自定义估值器,获得如: 0,3,6,9,...,96,99
3.1 自定义估值器
TypeEvaluator接口
public interface TypeEvaluator<T> {
//fraction进度值
public T evaluate(float fraction, T startValue, T endValue);
}
1.自定义估值器
package com.cupster.animation;
import android.animation.TypeEvaluator;
/**
* 此处代码为郭霖大神编写的自定义Evaluator,用于扩展属性动画:"color",
* 使用该动画的View需设置对应public void setColor,并在其中调用invalidate()
*/
public class ColorEvaluator implements TypeEvaluator {
private int mCurrentRed = -1;
private int mCurrentGreen = -1;
private int mCurrentBlue = -1;
@Override
public Object evaluate(float fraction, Object startValue, Object endValue) {
String startColor = (String) startValue;
String endColor = (String) endValue;
int startRed = Integer.parseInt(startColor.substring(1, 3), 16);
int startGreen = Integer.parseInt(startColor.substring(3, 5), 16);
int startBlue = Integer.parseInt(startColor.substring(5, 7), 16);
int endRed = Integer.parseInt(endColor.substring(1, 3), 16);
int endGreen = Integer.parseInt(endColor.substring(3, 5), 16);
int endBlue = Integer.parseInt(endColor.substring(5, 7), 16);
// 初始化颜色的值
if (mCurrentRed == -1) {
mCurrentRed = startRed;
}
if (mCurrentGreen == -1) {
mCurrentGreen = startGreen;
}
if (mCurrentBlue == -1) {
mCurrentBlue = startBlue;
}
// 计算初始颜色和结束颜色之间的差值
int redDiff = Math.abs(startRed - endRed);
int greenDiff = Math.abs(startGreen - endGreen);
int blueDiff = Math.abs(startBlue - endBlue);
int colorDiff = redDiff + greenDiff + blueDiff;
if (mCurrentRed != endRed) {
mCurrentRed = getCurrentColor(startRed, endRed, colorDiff, 0,
fraction);
} else if (mCurrentGreen != endGreen) {
mCurrentGreen = getCurrentColor(startGreen, endGreen, colorDiff,
redDiff, fraction);
} else if (mCurrentBlue != endBlue) {
mCurrentBlue = getCurrentColor(startBlue, endBlue, colorDiff,
redDiff + greenDiff, fraction);
}
// 将计算出的当前颜色的值组装返回
String currentColor = "#" + getHexString(mCurrentRed)
+ getHexString(mCurrentGreen) + getHexString(mCurrentBlue);
return currentColor;
}
/**
* 根据fraction值来计算当前的颜色。
*/
private int getCurrentColor(int startColor, int endColor, int colorDiff,
int offset, float fraction) {
int currentColor;
if (startColor > endColor) {
currentColor = (int) (startColor - (fraction * colorDiff - offset));
if (currentColor < endColor) {
currentColor = endColor;
}
} else {
currentColor = (int) (startColor + (fraction * colorDiff - offset));
if (currentColor > endColor) {
currentColor = endColor;
}
}
return currentColor;
}
/**
* 将10进制颜色值转换成16进制。
*/
private String getHexString(int value) {
String hexString = Integer.toHexString(value);
if (hexString.length() == 1) {
hexString = "0" + hexString;
}
return hexString;
}
}
2.封装方法
public static void propColorAnimator(ColorTextView target , String startColor , String endColor){
ObjectAnimator animator = ObjectAnimator.ofObject(target ,"color",new ColorEvaluator() ,startColor,endColor);
animator.setDuration(3000);
animator.start();
}
3.扩展View
class ColorTextView extends TextView {
public void setColor(String color){
setTextColor(Color.parseColor(color));
}
public ColorTextView(Context context) {
super(context);
}
public ColorTextView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
}
4.使用
img = findViewById(R.id.anim_view);
img.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
PropAnimatorHelper.propColorAnimator((ColorTextView) view,"#a7dbf7" ,"#ff8696");
}
});