简介
ObjectAnimator,是ValueAnimator的子类,支持利用目标视图的属性来实现动画效果。构造ObjectAnimator的时候,将会提取对应的参数来定义动画对象和对象属性。合适的get/set方法是视图实现属性动画的内部机理,动画过程中,系统将通过get/set方法来实现效果,也就是根据一定的规律来为View设置属性。
Animators可以用过资源文件或者是代码定义,当使用资源文件创建的时候,若使用PropertyValuesHolder和Keyframe可以创建出更加复杂的动画,使用PropertyValuesHolder可以实现几个属性的并行变化。
使用Keyframes,可以实现更复杂的动画过程中的属性变化方式。我们可以为每一个Keyframes明确一个fractional value(因子,0-1)来决定在整个动画过程中什么时候到达这个属性值。不设置fractions的时候,这些关键帧将会均匀的分布在整个动画过程中。至于那些没有指定value值的关键帧,将会在动画开始的时候推导出他们的 value。初次之外,我们可以给关键帧添加插值器,整个插值器将会在被设置的这一帧和前一帧动画之间。对于没有设置插值器的关键帧,将会给他们提供一个默认的插值器AccelerateDecelerateInterpolator
XML实现
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:repeatCount="1"
android:repeatMode="reverse">
<!-- BEGIN_INCLUDE(KeyframeResources) -->
<propertyValuesHolder android:propertyName="x">
<keyframe
android:fraction="0"
android:value="800" />
<keyframe
android:fraction=".2"
android:interpolator="@android:anim/accelerate_interpolator"
android:value="1000" />
<keyframe
android:fraction="1"
android:interpolator="@android:anim/accelerate_interpolator"
android:value="400" />
</propertyValuesHolder>
<propertyValuesHolder android:propertyName="y">
<keyframe />
<keyframe
android:fraction=".2"
android:interpolator="@android:anim/accelerate_interpolator"
android:value="300" />
<keyframe
android:interpolator="@android:anim/accelerate_interpolator"
android:value="1000" />
</propertyValuesHolder>
<!-- END_INCLUDE(KeyframeResources) -->
</objectAnimator>
objectAnimator属性值 | 含义 |
---|---|
android:propertyName | 属性名称 |
android:valueTo | 动画结束时属性的值 |
android:valueFrom | 动画开始时属性的值 |
android:duration | 动画时长 |
android:startOffset | 动画延迟几秒播放,调用start()方法后延迟 |
android:repeatCount | 动画重复次数 |
android:repeatMode | 动画重复的方式,restart/reverse |
android:valueType | 属性值类型,intType,floatType,colorType,pathType |
propertyValuesHolder属性值和objectAnimator基本相同
keyframe属性值 | 含义 |
---|---|
android:fraction | 插值因子 |
android:interpolator | 插值器,用在当前帧和前一帧之间 |
android:value | 需要设置的属性值 |
代码实现
public class MainActivity extends AppCompatActivity {
private int width;
private int height;
private ImageView imageView = null;
private ImageView loveImageView = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setNavigationIcon(R.drawable.left);
setSupportActionBar(toolbar);//设置ActionBar
getWidthAndHeight();//获取屏幕大小
imageView = (ImageView) findViewById(R.id.ball);
loveImageView = (ImageView) findViewById(R.id.love);
}
/*
心跳
*/
public void doAnimation(final View view) {
PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("alpha", 1f,
0.8f, 1f, 0.8f, 1.0f);
PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("scaleX", 0.6f,
0.8f, 1f, 0.8f, 1.0f);
PropertyValuesHolder pvhZ = PropertyValuesHolder.ofFloat("scaleY", 0.6f,
0.8f, 1f, 0.8f, 1.0f);
ObjectAnimator.ofPropertyValuesHolder(loveImageView, pvhX, pvhY, pvhZ).setDuration(1000).start();//创建属性动画并开始
}
/*
抛物线
*/
public void doGtAnimation(final View view) {
ObjectAnimator anim = ObjectAnimator.ofFloat(imageView, "yidong", 0, 1, 0).setDuration(3000);
/*设置动画更新监听器,通过手动设置属性来实现view属性的改变达到动画的效果*/
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float cVal = (Float) animation.getAnimatedValue();
imageView.setX(5 * cVal * 100);
imageView.setY(5 * cVal * 3 * cVal * 3 * 100);
}
});
/*设置动画过程监听器,监听开始结束取消等动作*/
anim.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
System.err.println("yidong -- onAnimationStart");
}
@Override
public void onAnimationEnd(Animator animation) {
System.err.println("yidong -- onAnimationEnd");
}
@Override
public void onAnimationCancel(Animator animation) {
System.err.println("yidong -- onAnimationCancel");
}
@Override
public void onAnimationRepeat(Animator animation) {
System.err.println("yidong -- onAnimationRepeat");
}
});
/*重复魔石*/
anim.setRepeatMode(ValueAnimator.RESTART);
/*重复次数*/
anim.setRepeatCount(2);
anim.start();
}
/*
转圈圈
*/
public void doCircleAnimation(View view) {
ObjectAnimator anim = ObjectAnimator.ofFloat(imageView, "yidong", 0, 2 * (float) Math.PI).setDuration(1000);
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
System.err.println("yidong -- value = " + animation.getAnimatedValue());
float cVal = (Float) animation.getAnimatedValue();
imageView.setX((float) Math.sin(cVal) * 200 + width / 2);
imageView.setY((float) Math.cos(cVal) * 200 + height / 2);
}
});
anim.setRepeatMode(ValueAnimator.REVERSE);
anim.setRepeatCount(-1);//无限重复
anim.start();
}
/*
从xml文件中提取动画
*/
public void doXmlAnimation(View view) {
Animator animator = AnimatorInflater.loadAnimator(this, R.animator.one);//从xml文件中添加动画
animator.setTarget(loveImageView);
animator.start();
}
/*
获取屏幕的宽高
*/
private void getWidthAndHeight() {
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
DisplayMetrics dm = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(dm);
width = dm.widthPixels;
height = dm.heightPixels;
System.err.println("yidong -- width = " + width);
System.err.println("yidong -- height = " + height);
}
}
实际效果
写在最后
属性动画的内容很丰富,这里只是提到了ObjectAnimator的一些简单实现,很深入和全面的东西,需要自己看源码,熟悉对应的API