Android属性动画

ValueAnimator
ValueAnimator是整个属性动画机制当中最核心的一个类,前面我们已经提到了,属性动画的运行机制是通过不断地对值进行操作来实现的,而初始值和结束值之间的动画过渡就是由ValueAnimator这个类来负责计算的。它的内部使用一种时间循环的机制来计算值与值之间的动画过渡,我们只需要将初始值和结束值提供给ValueAnimator,并且告诉它动画所需运行的时长,那么ValueAnimator就会自动帮我们完成从初始值平滑地过渡到结束值这样的效果。除此之外,ValueAnimator还负责管理动画的播放次数、播放模式、以及对动画设置监听器等,确实是一个非常重要的类。

但是ValueAnimator的用法却一点都不复杂,我们先从最简单的功能看起吧,比如说想要将一个值从1平滑过渡到0,时长300毫秒,就可以这样写:

ValueAnimator anim = ValueAnimator.ofFloat(1f, 0f);  
anim.setDuration(300);  
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {  
    @Override  
    public void onAnimationUpdate(ValueAnimator animation) {  
        float value = (float) animation.getAnimatedValue(); //得到动画变化的属性值 
        Log.d("zxy", "" + value);  
    }  
});  
anim.start(); 

很简单吧,调用ValueAnimator的ofFloat()方法就可以构建出一个ValueAnimator的实例,ofFloat()方法当中允许传入多个float类型的参数,这里传入1和0就表示将值从1平滑过渡到0,然后调用ValueAnimator的setDuration()方法来设置动画运行的时长,最后调用start()方法启动动画。
ValueAnimator anim = ValueAnimator.ofFloat(0f, 5f, 3f, 10f); 然后再开启动画即可。当然ValueAnimtor还有两个常用方法,即:ValueAnimator.ofInt(),ValueAnimator.ofObject(),除此之外,我们还可以调用setStartDelay()方法来设置动画延迟播放的时间,调用setRepeatCount()和setRepeatMode()方法来设置动画循环播放的次数以及循环播放的模式,循环模式包括RESTART和REVERSE两种,分别表示重新播放和倒序播放的意思。

下面我们来看一下ValueAnimtor的完整应用,当按钮点击时更新它的透明度:

private void valueAnim(){
		ValueAnimator animator = ValueAnimator.ofFloat(1f,0f,1f);
		animator.setDuration(5000);
		animator.addUpdateListener(new AnimatorUpdateListener() {
			@Override
			public void onAnimationUpdate(ValueAnimator animation) {
				float value = (Float) animation.getAnimatedValue();
				mBtnStart.setAlpha(value);//在动画更新监听器中,动画的值更新变化时设置button的透明度,可以在回调中不断更新View的多个属性,使用起来更加灵活,比如设置setTranslationX和setTranslationY可以让它斜着移动。
			}
		});
		animator.start();//开启后button的透明度会随着值的更新而更新
	}

ObjectAnimator
相比于ValueAnimator,ObjectAnimator可能才是我们最常接触到的类,因为ValueAnimator只不过是对值进行了一个平滑的动画过渡,但我们实际使用到这种功能的场景好像并不多。而ObjectAnimator则就不同了,它是可以直接对任意对象的任意属性进行动画操作的,比如说View的alpha属性。

不过虽说ObjectAnimator会更加常用一些,但是它其实是继承自ValueAnimator的,底层的动画实现机制也是基于ValueAnimator来完成的,因此ValueAnimator仍然是整个属性动画当中最核心的一个类。那么既然是继承关系,说明ValueAnimator中可以使用的方法在ObjectAnimator中也是可以正常使用的,它们的用法也非常类似,下面直接看代码:

private void startPropertyAnimOne() {//设置透明度变化从1——>0.1——>1——>0.5——>1,意思就是该对象经历四次透明度的渐变
		ObjectAnimator anim = ObjectAnimator.ofFloat(mTvText, "alpha", 1f,
				0.1f, 1f, 0.5f, 1f);//第一个参数传入的是任意对象,第二个参数传入的是想要对该对象的哪个属性进行动画操作,第三个参数是一个可变数组,描述的是该动画的初始值和结束值,动画的渐变效果是由ValueAnimator内部算法机制实现过度效果
		anim.setDuration(5000);//持续时间
		anim.addUpdateListener(new AnimatorUpdateListener() {//添加一个动画监听器,在动画执行过程中不停的回调
			
			@Override
			public void onAnimationUpdate(ValueAnimator animation) {
				float value = (Float) animation.getAnimatedValue();//得到动画变化的属性值
				Log.v("zxy", value+"");//从中可以看到透明度值会从1.0缓慢的变化到0.1再到1.0再到0.5再到1.0
			}
		});
		anim.start();
	}


private void startPropertyAnimTwo(){//设置旋转360度
		ObjectAnimator anim = ObjectAnimator.ofFloat(mTvText, "rotation", 0f,360f);
		anim.setDuration(5000);
		anim.start();
	}

private void startPropertyAnimThree(){//设置往x轴方向偏移然后回到原来的位置
		float translationX = mTvText.getTranslationX();//得到该控件移动前的X轴方向上的坐标
		ObjectAnimator anim = ObjectAnimator.ofFloat(mTvText, "translationX", translationX,-500f,translationX);//向右移动500像素,然后再移动到原来的位置
		anim.setDuration(5000);
		anim.start();
	}

private void startPropertyAnimFour(){//把TextView在垂直方向上放大3倍再还原
		ObjectAnimator anim = ObjectAnimator.ofFloat(mTvText, "scaleY", 1f, 3f, 1f);  
		anim.setDuration(5000);  
		anim.start();  
	}

那么textview对象中是不是有alpha属性这个值呢?没有,不仅textview没有这个属性,连它所有的父类也是没有这个属性的!这就奇怪了,textview当中并没有alpha这个属性,ObjectAnimator是如何进行操作的呢?怎么可以实现动画效果呢?其实ObjectAnimator内部的工作机制并不是直接对我们传入的属性名进行操作的,而是会去寻找这个属性名对应的get和set方法,然而TextView中并没有setAlpha和getAlpha方法啊?的却是这样,但是TextView是继承自View啊,我们通过查找View中的方法,发现了这两个方法,并且其它的rotation、translationX、等get和set方法也有,那么答案就有了,任何继承自View的类都有这些方法,通过set方法而把这个属性值设置给该对象,因此alpha属性才有所作用。

AnimatorSet
实现复合动画功能主要需要借助AnimatorSet这个类,这个类提供了一个play()方法,如果我们向这个方法中传入一个Animator对象(ValueAnimator或ObjectAnimator)将会返回一个AnimatorSet.Builder的实例,AnimatorSet.Builder中包括以下四个方法:

after(Animator anim) 将现有动画插入到该传入的动画(就是anim)之后执行
after(long delay) 将现有动画延迟指定毫秒后执行
before(Animator anim) 将现有动画插入到该传入的动画(就是anim)之前执行
with(Animator anim) 将现有动画和传入的动画同时执行
好的,有了这四个方法,我们就可以实现复合动画了,比如我们想要先让这个字体伸缩后再旋转的同时改变透明度,就可以这样做:

//复合动画
	private void animatorSet(){
		ObjectAnimator anim1 = ObjectAnimator.ofFloat(mTvText, "alpha", 1f,
				0.1f, 1f, 0.5f, 1f);
		ObjectAnimator anim2 = ObjectAnimator.ofFloat(mTvText, "rotation", 0f,360f);
		ObjectAnimator anim3 = ObjectAnimator.ofFloat(mTvText, "scaleY", 1f, 3f, 1f);  
		AnimatorSet animSet = new AnimatorSet();//定义一个AnimatorSet对象
		animSet.play(anim1).with(anim2).after(anim3);//anim3先执行,然后再同步执行anim1、anim2。【注意】先执行的anim3动画会执行6s,然后anim1和anim2一起也执行6s
		animSet.setDuration(6000);
		animSet.addListener(new AnimatorListenerAdapter() {//设置动画监听器,监听该动画的开始、停止、取消、结束等状态,我们往往会用AnimtorListener适配器类来只实现我们需要的方法
 
			@Override
			public void onAnimationEnd(Animator animation) {
				super.onAnimationEnd(animation);
				//动画开始,do sthing...
			}
 
			@Override
			public void onAnimationStart(Animator animation) {
				super.onAnimationStart(animation);
				//动画结束,do sthing...
			}
			
		});
		animSet.start();
	}

在很多时候,我们希望可以监听到动画的各种事件,比如动画何时开始,何时结束,然后在开始或者结束的时候去执行一些逻辑处理。这个功能是完全可以实现的,Animator类当中提供了一个addListener()方法,这个方法接收一个AnimatorListener,我们只需要去实现这个AnimatorListener就可以监听动画的各种事件了。

大家已经知道,ObjectAnimator是继承自ValueAnimator的,而ValueAnimator又是继承自Animator的,因此不管是ValueAnimator还是ObjectAnimator都是可以使用addListener()这个方法的。另外AnimatorSet也是继承自Animator的,因此addListener()这个方法算是个通用的方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值