Property Animation故名思议就是通过动画的方式改变对象的属性了,所以他也是功能最为强大的,可以这样说前面的帧动画和视图动画能做到的,他都能做到,并且更为强大
总的来说,属性动画就是,动画的执行类来设置动画操作的对象的属性、持续时间,开始和结束的属性值,时间差值等,然后系统会根据设置的参数动态的变化对象的属性。
之所以选择ObjectAnimator为第一个是因为,这个实现最简单一行代码,秒秒钟实现动画,下面看个例子:
我们想实现ListView的item的折叠和展开
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:id="@+id/file_list_item"
android:layout_width="match_parent"
android:layout_height="60dp"
android:orientation="vertical">
<LinearLayout
android:id="@+id/file_item_top"
android:layout_width="match_parent"
android:layout_height="60dp"
android:orientation="horizontal"
android:background="@color/zj_qianlan"
android:paddingBottom="4dp"
android:paddingTop="4dp">
</LinearLayout>
<LinearLayout
android:id="@+id/file_item_bottom"
android:layout_width="match_parent"
android:layout_height="60dp"
android:orientation="horizontal"
android:background="@color/zj_qianlan"
android:paddingBottom="4dp"
android:paddingTop="4dp">
</LinearLayout>
</LinearLayout>
</LinearLayout>
如上所示 我们外层LinearLayout
的高度为60dp
,里面也有两个都是60dp
,这样我们动态改变外层的高度来实现展开和折叠的动画
先说个简单的翻转动画
file_list_item = (LinearLayout)convertView.findViewById(R.id.file_list_item);
file_item_fold_layout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ObjectAnimator
.ofFloat(file_list_item, "rotationX", 0.0F, 360.0F)
.setDuration(500)
.start();
}
});
这里rotationX
是怎么来的,原来file_list_item
有setRotationX(float rotationX)
和getRotationX(float rotationX)
方法,所以可以这样做,但是我们想设置高度,但并没有setHeight()
和getHeight()
方法,怎们办呢,我们可以定义一个内部类
private static class ViewWrapper {
private ViewGroup mTarget;
public ViewWrapper(ViewGroup target) {
mTarget = target;
}
public int getHeight() {
return mTarget.getLayoutParams().height;
}
public void setHeight(int height) {
ViewGroup.LayoutParams vg = mTarget.getLayoutParams();
vg.height = height;
mTarget.setLayoutParams(vg);
}
}
然后就可以这样使用了
file_item_fold_layout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Integer height = file_list_item.getLayoutParams().height;
Integer targetHeight = 0;
if (height == DensityUtils.dp2px(getContext(), 60)) {
targetHeight = DensityUtils.dp2px(getContext(), 120);
} else {
targetHeight = DensityUtils.dp2px(getContext(), 60);
}
ViewWrapper viewWrapper = new ViewWrapper(file_list_item);
ObjectAnimator
.ofInt(viewWrapper, "height", targetHeight)
.setDuration(120)
.start();
}
});
注意的是ofInt()
方法 如果改的值为Int的话一定要用ofInt()
,用ofFloat()
是不会生效的
如果你操作对象的该属性方法里面,比如上例的setRotationX如果内部没有调用view的重绘,则你需要自己按照下面方式手动调用
anim.addUpdateListener(new AnimatorUpdateListener(){
@Override
public void onAnimationUpdate(ValueAnimator animation)
{
//view.postInvalidate();
//view.invalidate();
}
});
方式
public void rotateyAnimRun(final View view)
{
ObjectAnimator anim = ObjectAnimator
.ofFloat(view, "rotationX", 0.0F, 360.0F)
.setDuration(500);
anim.start();
anim.addUpdateListener(new AnimatorUpdateListener()
{
@Override
public void onAnimationUpdate(ValueAnimator animation)
{
float cVal = (Float) animation.getAnimatedValue();
view.setAlpha(cVal/360);
view.setScaleX(cVal/360);
view.setScaleY(cVal/360);
}
});
}
方式2
public void propertyValuesHolder(View view){
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();
}
ValueAnimator
是ObjectAnimator
的父类它没有ObjectAnimator
强大,但是会相对自由,他只会改变值,而我们可以设置View的属性值来实现动画
public void rotateyAnimRun(final View view)
{
ValueAnimator animator = ValueAnimator.ofFloat(0, 1.0f);
animator.setTarget(view);
animator.setDuration(300).start();
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener()
{
@Override
public void onAnimationUpdate(ValueAnimator animation)
{
Float value = (Float) animation.getAnimatedValue();
view.setAlpha(value);
view.setScaleX(value);
view.setScaleY(value);
}
});
}
AnimatorSet就是动画组 可以设置动画同时执行或先后执行
public void togetherRun(View view){
ObjectAnimator anim1 = ObjectAnimator.ofFloat(mBlueBall, "scaleX",
1.0f, 2f);
ObjectAnimator anim2 = ObjectAnimator.ofFloat(mBlueBall, "scaleY",
1.0f, 2f);
AnimatorSet animSet = new AnimatorSet();
animSet.setDuration(2000);
animSet.setInterpolator(new LinearInterpolator());
//两个动画同时执行
animSet.playTogether(anim1, anim2);
animSet.start();
}