之前只知道这两种动画是有区别的,区别是属性动画会修改View的属性。但是具体怎么回事一直没弄明白。
在阅读了网上的各种博客和源码后,大致搞懂了区别。
Tween动画通过view的matrix和alpha变量对view进行修改,但是并不会修改view自身属性。
而Property动画会修改view的自身属性,动画结束后的效果会实实在在的反应在view上。
例子如下:
MainActivity
package com.none.objectanimatordemo;
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.ScaleAnimation;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
public class MainActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ImageView img = (ImageView) findViewById(R.id.id_img);
img.setImageResource(R.mipmap.ic_launcher);
img.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "Image", Toast.LENGTH_SHORT).show();
}
});
Button btn = (Button) findViewById(R.id.id_btn);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ViewWrapper view = new ViewWrapper(img);
AnimatorSet set = new AnimatorSet();
ObjectAnimator width = ObjectAnimator.ofInt(view, "width", 200, 500).setDuration(3000);
ObjectAnimator height = ObjectAnimator.ofInt(view, "height", 200, 500).setDuration(3000);
set.playTogether(width, height);
set.setDuration(3000).start();
set.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
Log.d("TAG", "width: " + img.getWidth() + ", height: " + img.getHeight());
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
// ScaleAnimation scale = new ScaleAnimation(1.0f, 4.0f, 1.0f, 4.0f, Animation.RELATIVE_TO_PARENT, 0, Animation.RELATIVE_TO_PARENT, 0);
// scale.setFillAfter(true);
// scale.setDuration(3000);
// img.startAnimation(scale);
// scale.setAnimationListener(new Animation.AnimationListener() {
// @Override
// public void onAnimationStart(Animation animation) {
//
// }
//
// @Override
// public void onAnimationEnd(Animation animation) {
// Log.d("TAG", "width: " + img.getWidth() + ", height: " + img.getHeight());
// }
//
// @Override
// public void onAnimationRepeat(Animation animation) {
//
// }
// });
}
});
}
private static class ViewWrapper {
public ViewWrapper(View mTarget) {
this.mTarget = mTarget;
}
private View mTarget;
private int getWidth() {
return mTarget.getLayoutParams().width;
}
private void setWidth(int width) {
mTarget.getLayoutParams().width = width;
mTarget.requestLayout();
}
private int getHeight() {
return mTarget.getLayoutParams().height;
}
private void setHeight(int height) {
mTarget.getLayoutParams().height = height;
mTarget.requestLayout();
}
}
}
xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/id_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_circle"
android:text="@string/hello_world" />
<ImageView
android:id="@+id/id_img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="centerCrop"/>
</LinearLayout>
可以对比打印出来的img的宽高。scale动画后img的位置并没有改变,它的宽高也没有发生变化。
property动画则渐变的修改了img的宽高,最终达到了设定值。
例子中的属性动画在修改view的宽高时,会不断的requestlayout,该函数会导致view的measure,layout,draw重复调用。
属性动画会通过反射调用预设的setter和getter函数。