Android中有补件动画,帧动画和属性动画这几种常见动画。属性动画是3.0系统后推出的比较强大的动画。可以实现生活中大多数常见的动画功能。最近学习,用到了属性动画,结合源码和一些参考做一个记录。
1.基本使用
属性动画中常用到类ValueAnimator,ObjectAnimator,属性动画就是通过改变对象的属性实现动画,这两个类完成了对象的属性从初始值到结束的值的变化。
常用的方法:ofFloat(),ofInt(),ofObject();等。这些方法都有很多不同的重载方法,提供不同的参数实现差异的功能。
其中有一个:ValueAnimator bizerAnimator = ObjectAnimator.ofObject(typeEvalautor, param, param,param);这个需要传入一个估值器对象(TypeEvaluator)
其他方法:
bizerAnimator.setEvaluator();//设置一个估值器
bizerAnimator.setRepeatCount();//设置重复执行次数
bizerAnimator.setRepeatMode();//设置动画重复的模式
bizerAnimator.setTarget();//设置动画添加一个对象
bizerAnimator.setInterpolator();//设置一个插值器
这里插值器和估值器是实现一些复杂效果的关键。
基本使用举例:
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f,1f);
valueAnimator.setDuration(500);
valueAnimator.start();
一个基本的用法就是三行代码,实现500毫秒从0到1的变化;其实还可以传入多个参数,这个ofFloat()方法参数是边长参数。
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f,0.6f,0.2f,1f);
valueAnimator.setDuration(500);
valueAnimator.start();
上面实现了从0到0.6到0.2再到1的变化。
ObjectAnimator类:
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(imageView,"translationX",0f,200f,0f);
objectAnimator.setDuration(2000);
objectAnimator.start();
对一个ImageView 实现从起始位置到200px在到原始位置的变化,对应的:
"translationX"
是ImageView 的一个属性,这个属性在ImageView 中有个对应的set方法:
imageView.setTranslationX(0);
这里需要注意的一点就是:
在对一个对象进行操作的时候,第一个参数是对象示例,第二个参数一定是对应对象的一个属性并且有一个set方法去设置这个属性。动画执行过程就是通过这个属性设置值的。2.组合使用
组合使用就是把不同的动画效果放一起执行,可以是先后执行,也可以同时执行,这是实现一些复杂效果的关键。组合使用通过AnimatorSet 来组合。
比如对上的图片添加第一个移动,透明度变化和旋转三种动画,组合执行:
AnimatorSet animatorSet = new AnimatorSet();
ObjectAnimator translation = ObjectAnimator.ofFloat(imageView,"translationX",0f,300f,0f);
ObjectAnimator alpha = ObjectAnimator.ofFloat(imageView,"alpha",1f,0f,1f);
ObjectAnimator rotationY = ObjectAnimator.ofFloat(imageView,"rotationY",0f,360f);
//animatorSet.playSequentially(translation,alpha,rotationY);//按顺序执行位置移动,透明度变化,和旋转三个动画效果。
//animatorSet.play(translation).with(alpha).before(rotationY);//执行translation同时执行alpha 设置,在执行rotationY之前。
animatorSet.playTogether(translation,alpha,rotationY);//三个同时执行
animatorSet.setDuration(3000);
animatorSet.start();
以上代码创建了三个通话效果,通过不同的方法组合不同的执行效果。
属性动画的基本使用就是这些,如果代码操作不方便还可以写xml,在项目中使用。直接在代码中加载设置执行。
加载执行:
Animator animator = AnimatorInflater.loadAnimator(this,R.animator.animator1);
animator.setTarget(imageView);
animator.start();
仔细的看看xml代码,其实没有直接java创建动画方便,java中属性在一个动画可以重复操作如:位置移动,从左到右,在到左。
3.实际应用
如果还需要其他的复杂效果就要通过我们自定义来实现了。比如网络中的一些弹跳效果,水波效果等,这里了解一些概念。
估值器:
所谓估值器从名称上一直没有理解明白。实际就是实现一个逻辑处理的方法。
估值器实现了一个接口重写了evaluate()方法。
public interface TypeEvaluator {
/**
* This function returns the result of linearly interpolating the start and end values, with
* fraction
representing the proportion between the start and end values. The
* calculation is a simple parametric calculation: result = x0 + t * (x1 - x0)
,
* where x0
is startValue
, x1
is endValue
,
* and t
is fraction
.
*
* @param fraction The fraction from the starting to the ending values
* @param startValue The start value.
* @param endValue The end value.
* @return A linear interpolation between the start and end values, given the
* fraction
parameter.
*/
public T evaluate(float fraction, T startValue, T endValue);
}
看几个个系统提供的估值器代码:
public class IntEvaluator implements TypeEvaluator {
/**
* This function returns the result of linearly interpolating the start and end values, with
* fraction
representing the proportion between the start and end values. The
* calculation is a simple parametric calculation: result = x0 + t * (v1 - v0)
,
* where x0
is startValue
, x1
is endValue
,
* and t
is fraction
.
*
* @param fraction The fraction from the starting to the ending values
* @param startValue The start value; should be of type int
or
* Integer
* @param endValue The end value; should be of type int
or Integer
* @return A linear interpolation between the start and end values, given the
* fraction
parameter.
*/
public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
int startInt = startValue;
return (int)(startInt + fraction * (endValue - startInt));
}
}
上面是一个整数估值器,evaluate();方法就是进行一个计算处理在返回去。
public class PointFEvaluator implements TypeEvaluator {
private PointF mPoint;
public PointFEvaluator() {
}
public PointFEvaluator(PointF reuse) {
mPoint = reuse;
}
/**
* This function returns the result of linearly interpolating the start and
* end PointF values, with fraction
representing the proportion
* between the start and end values. The calculation is a simple parametric
* calculation on each of the separate components in the PointF objects
* (x, y).
*
* If {@link #PointFEvaluator(android.graphics.PointF)} was used to construct
* this PointFEvaluator, the object returned will be the reuse
* passed into the constructor.
*
* @param fraction The fraction from the starting to the ending values
* @param startValue The start PointF
* @param endValue The end PointF
* @return A linear interpolation between the start and end values, given the
* fraction
parameter.
*/
@Override
public PointF evaluate(float fraction, PointF startValue, PointF endValue) {
float x = startValue.x + (fraction * (endValue.x - startValue.x));
float y = startValue.y + (fraction * (endValue.y - startValue.y));
if (mPoint != null) {
mPoint.set(x, y);
return mPoint;
} else {
return new PointF(x, y);
}
}
}
PointFEvaluator 中evaluate()方法对两个PointF进行处理,最后返回。从上面看,估值器就是对指定的一些参数按照我们的需求,重新处理生成一个新的参数给动画执行。
估值器也是实现了一个接口和方法。
public interface TimeInterpolator {
/**
* Maps a value representing the elapsed fraction of an animation to a value that represents
* the interpolated fraction. This interpolated value is then multiplied by the change in
* value of an animation to derive the animated value at the current elapsed animation time.
*
* @param input A value between 0 and 1.0 indicating our current point
* in the animation where 0 represents the start and 1.0 represents
* the end
* @return The interpolation value. This value can be more than 1.0 for
* interpolators which overshoot their targets, or less than 0 for
* interpolators that undershoot their targets.
*/
float getInterpolation(float input);
}
系统提供了一些常用的插值器:
线性插值器,让动画成线性运动执行。对于接口的方法getInterpolation()直接返回数据,没有处理。
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()方法返回值是一个进行了乘法或者多次幂函数计算,从数学上说这就是一个幂函数曲线加速。
Math.pow(input, mDoubleFactor);
public class AccelerateInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {
private final float mFactor;
private final double mDoubleFactor;
public AccelerateInterpolator() {
mFactor = 1.0f;
mDoubleFactor = 2.0;
}
/**
* Constructor
*
* @param factor Degree to which the animation should be eased. Seting
* factor to 1.0f produces a y=x^2 parabola. Increasing factor above
* 1.0f exaggerates the ease-in effect (i.e., it starts even
* slower and ends evens faster)
*/
public AccelerateInterpolator(float factor) {
mFactor = factor;
mDoubleFactor = 2 * mFactor;
}
public AccelerateInterpolator(Context context, AttributeSet attrs) {
this(context.getResources(), context.getTheme(), attrs);
}
/** @hide */
public AccelerateInterpolator(Resources res, Theme theme, AttributeSet attrs) {
TypedArray a;
if (theme != null) {
a = theme.obtainStyledAttributes(attrs, R.styleable.AccelerateInterpolator, 0, 0);
} else {
a = res.obtainAttributes(attrs, R.styleable.AccelerateInterpolator);
}
mFactor = a.getFloat(R.styleable.AccelerateInterpolator_factor, 1.0f);
mDoubleFactor = 2 * mFactor;
setChangingConfiguration(a.getChangingConfigurations());
a.recycle();
}
public float getInterpolation(float input) {
if (mFactor == 1.0f) {
return input * input;
} else {
return (float)Math.pow(input, mDoubleFactor);
}
}
/** @hide */
@Override
public long createNativeInterpolator() {
return NativeInterpolatorFactoryHelper.createAccelerateInterpolator(mFactor);
}
通过上述系统代码的查看我们大致了解了,插值器就是通过一些数学计算,让当前时间的动画值改变,从而达到一定效果。
总的来说,估值器是处理了动画当前的数据,而插值器就对当前执行速度操作,达到一定效果。后边在对实际的自定义做练习。
参考资料:
http://www.jianshu.com/p/02deec7bf8f0
http://www.cnblogs.com/mengdd/p/3346003.html