忙了几天,又到周五了,虽然周五写bolg好像很少人看,不过无所谓啦。主要总结和自己看看。
本文承接和ys一起学动画——传统动画与属性动画(一) 一文继续介绍关于属性动画的一些知识和自己的demo。
本来打算再往demo里面新加一点内容的。。后来忙了一下,就没高兴写了。。
好了,进入正题。
属性动画
属性动画(Property Animation)是一个很强劲的动画框架,几乎可以为所有的事物加上动画效果。你可以定义一个动画去改变任何对象的属性,不管该对象是否在屏幕上,都可以进行绘制。一个属性动画在某一个时间段,改变的是一个对象的一个属性值(一个对象的一个字段)。原理就是这样。
属性动画相关的类
ObjectAnimator 对象动画执行类
ValueAnimator 值动画执行类
AnimatorSet 一组动画的执行,有多种方式(一起执行,自定义顺序执行等)
AnimtorInflater 加载xml文件类
TypeEvaluator 类型估值,主要用于设置动画操作属性的值
TimeInterpolator 时间插值器
属性动画的属性
Duration:
动画的持续时间
TimeInterpolation:
用于定义动画变化率的接口,所有插值器都必须实现此接口,有线性,非线性插值器。
TypeEvaluator:
用于定义属性值计算方式的接口,有int,float,color类型,根据属性的起始、结束值和插值一起计算出当前时间的属性值,可以使用PropertyValuesHolder来捆绑多个值的变化。
Animation sets:
动画集合,即可以同时对一个对象应用多个动画,这些动画可以同时播放也可以对不同动画设置不同的延迟
Frame refreash delay:
多少时间刷新一次,即每隔多少时间计算一次属性值,默认为10ms,最终刷新时间还受系统进程调度与硬件的影响
Repeat Country and behavoir:
重复次数与方式,如播放3次、5次、无限循环,可以让此动画一直重复,或播放完时向反向播放
对于View的属性来说:
1)translationX 和 translationY:这两个属性控制了View所处的位置,
它们的值是由layout容器设置的,是相对于坐标原点(0,0左上角)的一个偏移量。
2)rotation, rotationX 和 rotationY:控制View绕着轴点(pivotX和pivotY)旋转。它的表现跟Tween Animation中的RotateAnimation不一致。
RotateAnimation 的旋转,表现为平面的旋转
而rotationX、Y 旋转,是立体的旋转,默认是以View的中心点,做rotation(x,y)过中心点的直线,面向该直线进行翻转
3)scaleX 和 scaleY:控制View基于pivotX和pivotY的缩放。
4)pivotX 和 pivotY:旋转的轴点和缩放的基准点,默认是View的中心点。
5)x 和 y:描述了view在其父容器中的最终位置,是左上角坐标和偏移量(translationX,translationY)的和。
6)aplha:透明度,1是完全不透明,0是完全透明。
具体使用方法
通过调用执行类的ofFloat等方法就可以完成对动画的初始化,支持的值类型有float,int,keyframe,object以及PropertyValuesHolder。当然,不要忘记调用setDuration和start喔。
1.ObjectAnimator
对象动画,顾名思义,你可以为其指定一个Target对象,然后对其的某个属性进行值的变化从而达到动画效果。使用对象动画有两个条件:
①需要变化的属性必须要有对应的set,get方法;
②指定的属性必须是UI相关的,不然看不到效果。
//方法一 直接使用,单属性
ObjectAnimator//
.ofFloat(view, "rotationX", 0.0F, 360.0F)//参数:变化的View,变化的属性,变化的值(为可变长参数)
.setDuration(500)// 变化的总时长
.start(); // 启动动画
欸对了,听说换成妹子图才有人气,我得马上试试。
//方法二,为动画设置监听器,重写onAnimationUpdate自己实现多个属性的修改(可对相同的值进行不同处理)
ObjectAnimator anim = ObjectAnimator//
.ofFloat(view, "zhy", 1.0F, 1.5F)//
.setDuration(500);//
anim.start();
anim.addUpdateListener(new AnimatorUpdateListener()
{
@Override
public void onAnimationUpdate(ValueAnimator animation)
{
float cVal = (Float) animation.getAnimatedValue();
view.setAlpha(cVal);
view.setScaleX(cVal);
view.setScaleY(cVal);
}
});
//方法三,使用PropertyValuesHolder 捆绑多个需要改变的属性字段(可设置不同的值)
PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("alpha", 1f,
0f, 1f);
PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("scaleX", 1f,
0, 1f);
PropertyValuesHolder pvhZ = PropertyValuesHolder.ofFloat("scaleY", 1f,
0, 1f);
ObjectAnimator.ofPropertyValuesHolder(view, pvhX, pvhY,pvhZ).setDuration(1000).start();
2.ValueAnimator
值动画仅仅接受值作为参数,不需要之前的属性名,自然也没有了必须用对象得有set、get方法的限制。但是往往需要我们自己去实现它的update逻辑。
这里我实现了一个自由落体效果
/**
* 自由落体
* @param view
*/
public void verticalRun( View view)
{
ValueAnimator animator = ValueAnimator.ofFloat(0.0f,1f);
animator.setTarget(mBlueBall1);
animator.setDuration(1000).start();
animator.setInterpolator(new LinearInterpolator());
animator.addListener(new AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
// TODO Auto-generated method stub
Log.i(TAG,"drop start");
}
@Override
public void onAnimationRepeat(Animator animation) {
// TODO Auto-generated method stub
Log.i(TAG,"drop repeat");
}
@Override
public void onAnimationEnd(Animator animation) {
// TODO Auto-generated method stub
Log.i(TAG,"drop end");
}
@Override
public void onAnimationCancel(Animator animation) {
// TODO Auto-generated method stub
Log.i(TAG,"drop cancel");
}
});
animator.addUpdateListener(new AnimatorUpdateListener()
{
@Override
public void onAnimationUpdate(ValueAnimator animation)
{
//自己实现逻辑
float temp = (Float) animation.getAnimatedValue();
mBlueBall1.setTranslationY((float)(mScreenHeight - mBlueBall.getHeight()) * temp * temp);
}
});
}
还有一个抛物线效果
/**
* 抛物线
* @param view
*/
public void paowuxian(View view)
{
ValueAnimator valueAnimator = new ValueAnimator();
valueAnimator.setDuration(1000);
valueAnimator.setObjectValues(new PointF(0, 0),new PointF(mScreenWidth - mBlueBall.getWidth(),mScreenHeight - mBlueBall1.getHeight()));
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.setEvaluator(new TypeEvaluator<PointF>()
{
// fraction = t / duration
@Override
public PointF evaluate(float fraction, PointF startValue,
PointF endValue)
{
float maxa = (float) (endValue.x - startValue.x);
float maxb = (float) (endValue.y - startValue.y);
PointF point = new PointF();
point.x = maxa * fraction;
point.y = maxb * (fraction * fraction);
return point;
}
});
valueAnimator.start();
valueAnimator.addUpdateListener(new AnimatorUpdateListener()
{
@Override
public void onAnimationUpdate(ValueAnimator animation)
{
PointF point = (PointF) animation.getAnimatedValue();
mBlueBall.setTranslationX(point.x);
mBlueBall.setTranslationY(point.y);
}
});
}
两球同时落地(需要都使用线性时间插值器,才能达到这样的效果):
3.AnimatorSet
一组动画的执行,有多种方式(一起执行,自定义顺序执行等)
简单易懂的代码:
private void onebyone() {
// TODO Auto-generated method stub
float cx = mBlueBall.getX();
ObjectAnimator anim1 = ObjectAnimator.ofFloat(mBlueBall, "scaleX",
1.0f, 2f);
ObjectAnimator anim2 = ObjectAnimator.ofFloat(mBlueBall, "scaleY",
1.0f, 2f);
ObjectAnimator anim3 = ObjectAnimator.ofFloat(mBlueBall,
"x", cx , 0f);
ObjectAnimator anim4 = ObjectAnimator.ofFloat(mBlueBall,
"x", cx);
/**
* anim1,anim2,anim3,anim4依次执行
*/
AnimatorSet animSet = new AnimatorSet();
animSet.play(anim1).before(anim2);
animSet.play(anim2).before(anim3);
animSet.play(anim4).after(anim3);
animSet.setDuration(2000);
animSet.start();
}
private void together() {
// TODO Auto-generated method stub
ObjectAnimator anim1 = ObjectAnimator.ofFloat(mBlueBall, "scaleX",
0.5f, 2f ,0.5f);
ObjectAnimator anim2 = ObjectAnimator.ofFloat(mBlueBall, "scaleY",
0.5f, 2f ,0.5f);
ObjectAnimator anim3 = ObjectAnimator.ofFloat(mBlueBall, "alpha",
1.0f, 0.0f ,1.0f);
AnimatorSet animSet = new AnimatorSet();
animSet.setDuration(2000);
animSet.setInterpolator(new LinearInterpolator());
//一起执行
animSet.playTogether(anim1, anim2,anim3);
animSet.start();
}
(稍后会补充一些关于LayoutAnimator的内容,插值器前面已经讲了这边我就不再赘述了)
小结
其实属性动画用起来没有那么困难,做出来效果也蛮不错的,这里放出demo给大家下载。以后的demo都免费提供吧 。