Property Animator 属性动画概述与示例

Property Animation 属性动画

       属性动画是一个强大的框架,它几乎可以让你的所有东西做动画,你可以随着时间的推移通过更改他们的属性来定义动画,无论它是否绘制在屏幕上,一个属性动画是在指定的时间内去改变属性(一个对象的字段)。你指定想要完成动画的对象的属性去做动画,比如你在屏幕上的位置,想让它动多久,和动画的属性值。


属性动画允许你定义以下特征:

Duraiton 时间:指定的动画发生的时间端,默认是300ms。

Time interpolation 插值器:指定属性的值,该值是由当前动画的时间计算而来的。

Repeat count and behavio 重复次数和行为:指定动画重复次数和动画反向播放。

Animator sets 动画集:指定多个动画同时播放或者按照一定的逻辑有序的播放。

Frame refresh delay 帧刷新延迟:指定动画刷新的延迟时间。


How Property Animation Works 属性动画是如何工作的

       首先,让我们看看如何在动画作品用一个简单的例子。图1描绘了动画与其x属性,它表示在画面上的水平位置的假想物体。动画的持续时间被设定为40毫秒,并以行进的距离是40个像素。每隔10毫秒,这是默认的帧刷新速率,目的是通过10个像素沿水平方向移动。在40毫秒结束时,动画停止,并且对象结束于水平位置40,这是与线性内插的动画的例子,这意味着在一个恒定速度的物体运动。


还可以指定动画具有非线性内插。图2示出了加速时的动画开始一个假想的对象,并减速在动画结束。对象仍移动40个像素在40毫秒的,但非直线。在开始的时候,这个动画加速到中间点,然后减速,从中间点,直到动画结束。如图2所示,行进的距离在开始和动画的端小于在中间。


让我们来详细看一下属性动画系统的重要组成部分,如何将计算如上所示的那些动画。图3示出了主要的类与另一个是如何工作的。


原理一大堆:

ValueAnimator 对象跟踪你的动画时间,如动画已经运行了多长时间,动画正在运行时的当前属性值。

ValueAnimator封装了TimeInterpolator ,它定义动画差值和一个TypeEvaluator,它定义了如何去计算这些动画的属性,

创建一个动画,要给它一个起始值和终点值,运行期间的时间。启用start()之后动画就开始运行了,在整个动画,所述ValueAnimator计算0和1之间的经过部分,基于该动画的持续时间和还有多少时间结束。经过的分数表示的时间,该动画已完成的百分比,0表示0%和1的含义为100%。例如,在图1中,在t的经过分率=10毫秒将是0.25,因为总的持续时间为t= 40毫秒。


How Property Animation Differs from View Animation 属性动画与View动画的区别

该视图的动画系统提供的能力,只有动画视图对象,所以如果你想制作动画的非视图对象,你必须实现自己的代码来这样做。该视图的动画系统也受限于一个事实,即它仅公开了一个查看对象的几个方面进行动画,如一个视图的缩放和旋转,但不是背景颜色,例如。

视图动画系统的另一个缺点是,它仅修改其视图绘制,而不是实际的视图本身。举例来说,如果你的动画一个按钮在屏幕上移动,按钮绘制正确的,但在这里你可以点击按钮的实际位置不会改变,所以你要实现你自己的逻辑来处理这个问题。

随着物业动画系统,这些约束完全删除,并且可以设置动画的任何对象(视图和非视图)的任何属性和对象本身实际上被修改。属性动画系统也是它执行的动画的方式更加健壮。在一个较高的水平,分配给动画师要动画的属性,如颜色,位置或大小,可以定义动画的方面,如插补和多个动画同步。


API 概述:

你可以发现,大部分的属性动画系统API的android.animation。因为视图动画系统已经定义了android.view.animation许多插值,你可以使用这些插值物业动画系统也是如此。


属性动画使用示例:

新建application,创建布局文件,创建类,下面给一个ImageView属性动画,之后的变化只贴出动画方法。动画是通过点击ImageView自身触发的。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/parent"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <ImageView
        android:id="@+id/image_view_01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/png_01" />

   

</LinearLayout>
java

mView.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View arg0) {
				
				animator09(arg0);
			}
		});
反转动画:

private void animator01(View view) {

		ObjectAnimator.ofFloat(view, "rotationX", 0.0F, 360F).setDuration(500).start();
	}


缩小淡出动画

private void animator02(final View view) {
		ObjectAnimator mAnimator = ObjectAnimator.ofFloat(view, "zhy", 1.0F, 0.0F).setDuration(500);
		mAnimator.start();
		mAnimator.addUpdateListener(new AnimatorUpdateListener() {

			@Override
			public void onAnimationUpdate(ValueAnimator animation) {
				float cVal = (Float) animation.getAnimatedValue();
				view.setAlpha(cVal);
				view.setScaleX(cVal);
				view.setScaleY(cVal);
			}
		});
	}

放大缩小再放大动画,放大同时变化透明度

// 复合动画,放大,透明度变化
	@SuppressLint("NewApi")
	private void animator03(View view) {
		PropertyValuesHolder pX = PropertyValuesHolder.ofFloat("alpha", 1F, 0F, 1F);
		PropertyValuesHolder pY = PropertyValuesHolder.ofFloat("scaleX", 1F, 0F, 1F);
		PropertyValuesHolder pZ = PropertyValuesHolder.ofFloat("scaleY", 1F, 0F, 1F);
		ObjectAnimator.ofPropertyValuesHolder(view, pX, pY, pZ).setDuration(500).start();
	}


自由落体

// 自由落体
	@SuppressLint("NewApi")
	private void animator04(final View view) {
		ValueAnimator animator = ValueAnimator.ofFloat(0, 300);
		animator.setTarget(view);
		animator.setDuration(1000);
		animator.start();
		animator.addUpdateListener(new AnimatorUpdateListener() {

			@Override
			public void onAnimationUpdate(ValueAnimator arg0) {
				// TODO Auto-generated method stub
				view.setTranslationY((Float) arg0.getAnimatedValue());
			}
		});
	}


抛物线

private void animator05(final View view) {
		ValueAnimator animator = ValueAnimator.ofFloat();
		animator.setDuration(3000);
		animator.setObjectValues(new PointF(0, 0));
		animator.setInterpolator(new LinearInterpolator());
		animator.setEvaluator(new TypeEvaluator<PointF>() {

			@Override
			public PointF evaluate(float fraction, PointF startValue, PointF endValue) {
				// Log.i("ABC", fraction + "");
				PointF mPointF = new PointF();
				mPointF.x = 200 * fraction * 3;
				mPointF.y = 0.5f * 200 * fraction * 3 * fraction * 3;
				return mPointF;
			}
		});
		animator.start();
		animator.addUpdateListener(new AnimatorUpdateListener() {

			@Override
			public void onAnimationUpdate(ValueAnimator arg0) {
				// TODO Auto-generated method stub
				PointF mPointF = (PointF) arg0.getAnimatedValue();
				view.setX(mPointF.x);
				view.setY(mPointF.y);
			}
		});
		animator.addListener(new AnimatorListener() {

			@Override
			public void onAnimationStart(Animator arg0) {
				Log.i("ABC", "1");
			}

			@Override
			public void onAnimationRepeat(Animator arg0) {
				Log.i("ABC", "2");
			}

			@Override
			public void onAnimationEnd(Animator arg0) {
				Log.i("ABC", "3");
			}

			@Override
			public void onAnimationCancel(Animator arg0) {
				Log.i("ABC", "4");
			}
		});
		animator.addListener(new AnimatorListenerAdapter() {

			@Override
			public void onAnimationEnd(Animator animation) {
				// TODO Auto-generated method stub
				super.onAnimationEnd(animation);
			}
		});
	}
private void animator06(View view) {
		ObjectAnimator mAniX = ObjectAnimator.ofFloat(view, "scaleX", 1.0F, 2.0F);
		ObjectAnimator mAniY = ObjectAnimator.ofFloat(view, "scaleY", 1.0F, 2.0F);
		AnimatorSet animSet = new AnimatorSet();
		animSet.setDuration(2000);
		animSet.setInterpolator(new LinearInterpolator());
		animSet.playTogether(mAniX, mAniY);
		animSet.start();
	}


多动画同时进行

private void animator06(View view) {
		ObjectAnimator mAniX = ObjectAnimator.ofFloat(view, "scaleX", 1.0F, 2.0F);
		ObjectAnimator mAniY = ObjectAnimator.ofFloat(view, "scaleY", 1.0F, 2.0F);
		AnimatorSet animSet = new AnimatorSet();
		animSet.setDuration(2000);
		animSet.setInterpolator(new LinearInterpolator());
		animSet.playTogether(mAniX, mAniY);
		animSet.start();
	}

多动画有序进行

private void animator07(View view) {
		float cx = view.getX();
		ObjectAnimator mAni1 = ObjectAnimator.ofFloat(view, "scaleX", 1.0F, 2.0F);
		ObjectAnimator mAni2 = ObjectAnimator.ofFloat(view, "scaleY", 1.0F, 2.0F);
		ObjectAnimator mAni3 = ObjectAnimator.ofFloat(view, "x", cx, 0f);
		ObjectAnimator mAni4 = ObjectAnimator.ofFloat(view, "y", cx);
		AnimatorSet set = new AnimatorSet();
		set.play(mAni1).with(mAni2);
		set.play(mAni2).with(mAni3);
		set.play(mAni4).after(mAni3);
		set.setDuration(1000).start();
	}
效果同上。


xml定义属性动画

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >

    <objectAnimator
        android:duration="1000"
        android:propertyName="scaleX"
        android:valueFrom="1"
        android:valueTo="0.5" >
    </objectAnimator>
    <objectAnimator
        android:duration="1000"
        android:propertyName="scaleY"
        android:valueFrom="1"
        android:valueTo="0.5" >
    </objectAnimator>

</set>

private void animator08(View view) {
		Animator animator = AnimatorInflater.loadAnimator(this, R.animator.scalexy);
		view.setPivotX(0);
		view.setPivotY(0);
		view.invalidate();
		animator.setTarget(view);
		animator.start();
	}


View的animator属性设置动画

private void animator09(final View v) {
		v.animate().alpha(0).y(200).setDuration(500).withStartAction(new Runnable() {

			@Override
			public void run() {
				// TODO Auto-generated method stub

			}
		}).withEndAction(new Runnable() {

			@Override
			public void run() {
				// TODO Auto-generated method stub
				runOnUiThread(new Runnable() {
					@SuppressLint("NewApi")
					public void run() {
						v.setY(0);
						v.setAlpha(1.0f);
					}
				});
			}
		}).start();
	}


LayoutTransition 

LayoutTransition 对ViewGroup中的View改变进行动画显示

LayoutTransition.APPEARING                      view出现时自身view的动画。

LayoutTransition.CHANGE_APPEARING      view出现自身view此之外其他兄弟view的动画

LayoutTransition.DISAPPEARING                 view消失时本身view的动画

LayoutTransition.CHANGE_DISAPPEARING view消失时除自身view以外的兄弟view的动画

LayoutTransition.CHANGING                       不知道是干嘛的,试了好多情况没发现效果

java

public class MainActivity extends Activity {
	Button mAddBtn;
	ViewGroup group;

	//
	int btn = 0;
	GridLayout gridLayout = null;
	LayoutTransition mTransition;

	@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		group = (ViewGroup) findViewById(R.id.parent);

		mAddBtn = (Button) findViewById(R.id.add_btn);
		mAddBtn.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View arg0) {
				addBtn(arg0);
			}
		});
		gridLayout = new GridLayout(this);
		gridLayout.setColumnCount(5);
		group.addView(gridLayout);
		mTransition = new LayoutTransition();
		mTransition.setAnimator(LayoutTransition.APPEARING, mTransition.getAnimator(LayoutTransition.APPEARING));
		mTransition.setAnimator(LayoutTransition.CHANGE_APPEARING, mTransition.getAnimator(LayoutTransition.CHANGE_APPEARING));
		mTransition.setAnimator(LayoutTransition.DISAPPEARING, mTransition.getAnimator(LayoutTransition.DISAPPEARING));
		mTransition.setAnimator(LayoutTransition.CHANGE_DISAPPEARING,
				mTransition.getAnimator(LayoutTransition.CHANGE_DISAPPEARING));
		mTransition.setAnimator(LayoutTransition.CHANGING, mTransition.getAnimator(LayoutTransition.CHANGING));
		gridLayout.setLayoutTransition(mTransition);

	}

	

	@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
	@SuppressLint("NewApi")
	private void addBtn(View view) {
		final Button button = new Button(this);
		button.setText((++btn) + "");
		gridLayout.addView(button, Math.min(1, gridLayout.getChildCount()));
		button.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View arg0) {
				// TODO Auto-generated method stub
				gridLayout.removeView(button);
			}
		});
	}
}



posted @ 2015-02-12 23:33  顾明伟  阅读(293)  评论(0编辑  收藏  举报