Android动画之属性动画(PropertyAnimation)详解(一)

转载请注明出处:http://blog.youkuaiyun.com/xiaohao0724/article/details/54863112

前面我们学习了补间动画,今天我们来学习可以代替补间动画的属性动画 Property Animation

我们先来看一下补间动画和属性动画的区别:

补间动画通过动画改变控件的位置时,只是改变了View的显示效果并不会真正的改变View的属性(如View的真实位置等),控件的作用域还在原地,而且补间动画是只能够作用在View上。

属性动画通过动画改变控件的位置时,控件的真实位置会随着改变,控件的作用域在变换后的位置。

下面我们就来学习属性动画的平移、缩放、旋转、透明度变化和属性动画的一些组合动画。



属性动画的平移、缩放、旋转、透明度变化



属性动画的组合动画


一、先来看属性动画的平移、缩放、旋转、透明度变化

代码实现如下:
AnimationProperty.java
public class AnimationProperty {

	public static ObjectAnimator setAnimProperty(ObjectAnimator objectAnimator) {

		// objectAnimator.setRepeatCount(2); // 动画重复次数
		// 动画重复模式分别为:RESTART(重新播放)和REVERSE(往返播放)两种
		// objectAnimator.setRepeatMode(ObjectAnimator.RESTART);
		objectAnimator.setDuration(2000); // 动画播放时长
		// objectAnimator.start(); //开启动画
		// objectAnimator.setStartDelay(2000); // 延时开启动画
		// objectAnimator.cancel(); //停止动画
		// objectAnimator.end(); //直接到最终状态
		return objectAnimator;
	}

	public static ValueAnimator setAnimProperty(ValueAnimator valueAnimator) {

		valueAnimator.setRepeatCount(2);
		valueAnimator.setRepeatMode(ObjectAnimator.RESTART);
		valueAnimator.setDuration(2000).start();
		return valueAnimator;
	}

}

PropertyAnimationActivity.java

public class PropertyAnimationActivity extends Activity {

	protected static final String TAG = "Havorld";
	private ImageView imageView;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_property);

		imageView = (ImageView) findViewById(R.id.iv);
		imageView.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {

				Toast.makeText(getApplicationContext(), "点击了图片",
						Toast.LENGTH_SHORT).show();
			}
		});
	}

	/**
	 * 平移动画
	 */
	public void trans(View view) {

		/**
		 * imageView: 要作用的控件; translationY: 要作用动作的属性名 ; float... values:
		 * 可变参数是依次移动的位移
		 * 
		 */
		// ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(imageView,
		// "translationY", 20, 40, 80, 120, 160); //竖直平移
		ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(imageView,
				"translationX", 0, 50, 100, 150, 200, 250, 300); // 水平平移

		// 监听动画是否成功执行
		objectAnimator.addUpdateListener(new AnimatorUpdateListener() {

			@Override
			public void onAnimationUpdate(ValueAnimator animation) {

				float currentValue = (Float) animation.getAnimatedValue();
				Log.i(TAG, "currentValue:" + currentValue);
				// 直接设置动画
				// imageView.setTranslationX(translationX);
				// imageView.setTranslationY(translationY);
				// imageView.setScaleX(caleX);
				// imageView.setScaleY(scaleY);
				// imageView.setRotation(rotation);
				// imageView.setRotationX(rotation);
				// imageView.setRotationY(rotation);
				// imageView.setImageAlpha(alpha);
				// imageView.setAlpha(alpha);
			}
		});
		// 动画监听
		objectAnimator.addListener(new AnimatorListener() {

			// 动画开始执行
			@Override
			public void onAnimationStart(Animator animation) {

				Log.e(TAG, "onAnimationStart");
			}

			// 动画重复执行
			@Override
			public void onAnimationRepeat(Animator animation) {

				Log.e(TAG, "onAnimationRepeat");
			}

			// 动画执行完成
			@Override
			public void onAnimationEnd(Animator animation) {
				// 获取控件平移的距离
				float translationX = imageView.getTranslationX();
				Log.e(TAG, "translationX:" + translationX);
			}

			// 动画取消执行
			@Override
			public void onAnimationCancel(Animator animation) {

				Log.e(TAG, "onAnimationCancel");
			}
		});

		// 简化上述动画监听,可以复写上面的任意方法
		objectAnimator.addListener(new AnimatorListenerAdapter() {

		});

		// 设置动画属性并开启动画
		AnimationProperty.setAnimProperty(objectAnimator).start();

		// XmlTranslation();
		// valueAnimator();
	}

	/**
	 * 通过XML设置平移
	 */
	private void XmlTranslation() {
		// 通过XML设置属性动画
		Animator animator = AnimatorInflater.loadAnimator(this,
				R.animator.object_animator_translationx);
		animator.setTarget(imageView);
		animator.start();
	}

	/**
	 * 通过ValueAnimator设置平移
	 */
	private void valueAnimator() {

		ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1000);
		valueAnimator.setTarget(imageView);
		AnimationProperty.setAnimProperty(valueAnimator);
		valueAnimator.addUpdateListener(new AnimatorUpdateListener() {
			@Override
			public void onAnimationUpdate(ValueAnimator animation) {
				float animatedValue = (Float) animation.getAnimatedValue();
				imageView.setTranslationY(animatedValue);
			}
		});
	}

	/**
	 * 缩放动画
	 */
	public void scale(View view) {

		// 横向缩放
		ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(imageView,
				"scaleX", 1.0f, 1.2f, 1.5f, 1.8f, 2.0f, 1.8f, 1.5f, 1.0f);
		// 纵向缩放
		// ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(imageView,
		// "scaleY", 1.0f, 1.2f, 1.5f, 1.8f, 2.0f,1.8f, 0.5f,1.0f);
		// 通过代码设置属性动画
		AnimationProperty.setAnimProperty(objectAnimator).start();

	}

	/**
	 * 旋转动画
	 */
	public void rotate(View view) {

		ObjectAnimator objectAnimator = ObjectAnimator
				.ofFloat(imageView, "rotationX", 0, 60, 120, 150, 180, 210,
						240, 270, 300, 330, 360);
		AnimationProperty.setAnimProperty(objectAnimator).start();
	}

	/**
	 * 透明度变化动画
	 */
	public void alpha(View view) {

		ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(imageView,
				"alpha", 0, 0.1f, 0.3f, 0.5f, 0.8f, 1.0f);
		AnimationProperty.setAnimProperty(objectAnimator).start();
	}

}

activity_property.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"
    android:padding="10dp"
    tools:context=".PropertyAnimationActivity" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <Button
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:onClick="trans"
            android:text="平移" />

        <Button
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:onClick="scale"
            android:text="缩放" />

        <Button
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:onClick="rotate"
            android:text="旋转" />

        <Button
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:onClick="alpha"
            android:text="透明" />
    </LinearLayout>

    <ImageView
        android:id="@+id/iv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="10dp"
        android:src="@drawable/cl" />

</LinearLayout>

在代码中调用ObjectAnimator.ofFloat(imageView,"translationX", 0, 50, 100, 150, 200, 250, 300);
意思就是ObjectAnimator会不断地改变imageView对象的translationX属性的值从0变化到300。然后imageView对象根据translationX属性值的改变来不断刷新界面的显示,产生横向移动的动画效果。

ObjectAnimator是如何进行操作的呢?ObjectAnimator内部的工作机制是去寻找translationX这个属性名对应的get和set方法:
public void setTranslationX(float value);  
public float getTranslationX();  

imageView中确实有这两个方法:
imageView.getTranslationX();
imageView.setTranslationX(translationX);
这两个方法是由其父类View对象提供,所以使用ObjectAnimator.ofFloat()调用属性动画时对应的控件必须要有set和get方法。其他的scaleX,rotationX,alpha也是一样的道理。
注:使用ValueAnimator掉用属性动画时不需要其控件必须有set和get方法。

二、接下来看属性动画的组合动画

直接上代码:

PropertyGroupAnimationActivity.java

public class PropertyGroupAnimationActivity extends Activity {

	protected static final String TAG = "Havorld";
	private ImageView imageView;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_property_group);

		imageView = (ImageView) findViewById(R.id.iv);
		imageView.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {

				Toast.makeText(getApplicationContext(), "点击了图片",
						Toast.LENGTH_SHORT).show();
			}
		});

	}

	/**
	 * 组合动画一
	 */
	public void animatorSet(View view) {

		AnimatorSet animatorSet = new AnimatorSet();

		ObjectAnimator translationXAnimation = AnimationProperty
				.setAnimProperty(ObjectAnimator.ofFloat(imageView,
						"translationX", 0, 10, 20, 30, 40, 50));

		ObjectAnimator translationYAnimation = AnimationProperty
				.setAnimProperty(ObjectAnimator.ofFloat(imageView,
						"translationY", 0, 20, 40, 80, 100));

		ObjectAnimator scaleXAnimation = AnimationProperty
				.setAnimProperty(ObjectAnimator.ofFloat(imageView, "scaleX",
						1.0f, 1.2f, 1.5f, 1.8f, 2.0f, 1.8f, 1.5f, 1.0f));

		ObjectAnimator rotationAnimation = AnimationProperty
				.setAnimProperty(ObjectAnimator.ofFloat(imageView, "rotation",
						0, 60, 120, 150, 180, 210, 240, 270, 300, 330, 360));
		ObjectAnimator alphaAnimation = AnimationProperty
				.setAnimProperty(ObjectAnimator.ofFloat(imageView, "alpha", 0,
						0.1f, 0.3f, 0.5f, 0.8f, 1.0f));

		// after(Animator anim) 将现有动画插入到传入的动画之后执行
		// after(long delay) 将现有动画延迟指定毫秒后执行
		// before(Animator anim) 将现有动画插入到传入的动画之前执行
		// with(Animator anim) 将现有动画和传入的动画同时执行

		// 按顺序播放动画组合方法一,弦播放alphaAnimation动画后,开始一块播放translationXAnimation和translationYAnimation动画,
		// 完了之后再一块播放scaleXAnimation和rotationAnimation
		// animatorSet.play(translationXAnimation).with(translationYAnimation);
		// animatorSet.play(scaleXAnimation).with(rotationAnimation)
		// .after(alphaAnimation);

		// 按顺序播放动画组合方法二
		// animatorSet.playSequentially(translationXAnimation,translationYAnimation,scaleXAnimation,rotationAnimation,alphaAnimation);

		// 组合动画
		animatorSet.playTogether(translationXAnimation, translationYAnimation,
				scaleXAnimation, rotationAnimation, alphaAnimation);

		animatorSet.start();
	}

	/**
	 * 组合动画二
	 */
	public void viewProperty(View view) {

		ViewPropertyAnimator viewPropertyAnimator = imageView.animate();
		viewPropertyAnimator.x(20).y(30);//移动到坐标(20,30)处
		viewPropertyAnimator.alpha(0.5f);//设置控件透明度为0.5
	}

	/**
	 * 组合动画三
	 */
	public void propertyValuesHolder(View view) {

		PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX",
				1f, 0, 1f);
		PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY",
				1f, 0, 1f);
		PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1f,
				0f, 1f);
		PropertyValuesHolder rotation = PropertyValuesHolder.ofFloat(
				"rotation", 0, 90);
		ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(
				imageView, alpha, scaleX, scaleY, rotation);
		AnimationProperty.setAnimProperty(objectAnimator).start();

	}

	/**
	 * 一个动画实现多个效果
	 */
	public void groupAnimation(View view) {

		ObjectAnimator animator = ObjectAnimator.ofFloat(imageView, "Havorld",
				1.0F, 1.5F);
		ObjectAnimator objectAnimator = AnimationProperty
				.setAnimProperty(animator);

		//监听动画的执行
		objectAnimator.addUpdateListener(new AnimatorUpdateListener() {
			@Override
			public void onAnimationUpdate(ValueAnimator animation) {
				float animatedValue = (Float) animation.getAnimatedValue();
				Log.e(TAG, "animatedValue:" + animatedValue);
				imageView.setAlpha(animatedValue);
				imageView.setScaleX(animatedValue);
				imageView.setScaleY(animatedValue);
			}
		});
		objectAnimator.start();
	}

}

activity_property_group.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"
    tools:context=".PropertyAnimationActivity" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <Button
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:onClick="animatorSet"
            android:text="AnimatorSet"
            android:textSize="12sp" />

        <Button
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:onClick="viewProperty"
            android:text="ViewProperty"
            android:textSize="12sp" />

        <Button
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:ellipsize="end"
            android:onClick="propertyValuesHolder"
            android:singleLine="true"
            android:text="propertyValuesHolder"
            android:textSize="12sp" />
    </LinearLayout>

    <ImageView
        android:id="@+id/iv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="10dp"
        android:src="@drawable/cl" />

</LinearLayout>

点击下载源码


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值