(1)Animation动画类学习总结
AlphaAnimation,TranslateAnimation,ScaleAnimation,RotateAnimation.
透明度,位移,缩放,旋转
AlphaAnimation设定开始和结束的alpha值,float类型,0.0f到1.0f。
TranslateAnimation,设定4个,开始与结束的x,y坐标。注意,这里不是绝对坐标,而是距离当前组件所在位置的相对距离,给正数说明在组件右边,给负数说明在组件左边。
ScaleAnimation,设定开始和放大后的x,y倍数,浮点数,1.0f为原来组件大小。要设定一个点,动画相对于物件的X坐标的开始位置,和动画相对于物件的y坐标的开始位置(这个要多看下效果,不好描述,会决定动画缩放的效果和最后一帧的位置)
RotateAnimation,设定旋转的开始角度与结束角度。正数是顺时针转,负数是逆时针转.360为一周。还要设定组件围绕哪个点旋转。给出那个点的x,y坐标。
javacode里面引用res/anim下的xxx.xml文件:
AnimationmAnimation=AnimationUtils.loadAnimation(this,R.anim.xxx);//注意是AnimationUtils下的静态方法,util是utility的缩写,工具的意思
javacode里面用mAnimation.setDuration(3000)来设置动画持续的事件。
如果是res/drawable下的xml文件的话用。android:duration="150"
javacode里面用mAnimation.setFillAfter(true)让动画停止在最后一帧。
xml要在
系统默认是设置android:fillBefore="true",也就是让动画停止在第一帧,也就是组件最开始在布局文件中位置。
在xml中设定多种label可以让几种动画叠加一起播放,注意不是一个紧接一个播放的。如果想要紧接着播放,可以在代码中一个一个的设置,或者在xml中设置android:startOffset="",时间偏移,让动画经过一段时间后再启动。
至于动画重复多次播放,rotata对应的动画相对点以及scale对应的旋转点的位置如果在组件外如何设置,以及如何在java代码中实现多个动画同时启动的方式以后当用到后再探讨。
javacode中代码
//根据各自的构造方法来初始化一个实例对象
myAnimation_Alpha=newAlphaAnimation(0.1f, 1.0f);
myAnimation_Scale=new ScaleAnimation(0.0f, 1.4f, 0.0f, 1.4f,
Animation.RELATIVE_TO_SELF,0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
myAnimation_Translate=newTranslateAnimation(30.0f, -80.0f, 30.0f, 300.0f);
myAnimation_Rotate=newRotateAnimation(0.0f, +350.0f,
Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
(2)帧动画实现方式
res/drawable目录下放素材图片若干张。
res/drawable目录下建立animation.xml文件。
xml中设置label为
android:oneshot="false">
布局文件中的引用
android:layoutHeight="wrap_content"
android:layoutWidth="wrap_content"
android:src="@drawale/animation"
android:id="@+id/my_imageview">
代码中实现
ImageViewmyImageView=(ImageView)findViewById(R.id.my_imageview);
AnimationDrawablead=(AnimationDrawable)myImageView.getDrawable();//实例化res/drawable下的xml文件
ad.start();//开始动画
(2)Animation的进一步学习
两个动画同时播放:
方法一:
AnimationSet类
AnimationSetset=new AnimationSet(true);
set.addAnimation(Animationanimation);//典型用法
add几个Animation,这几个animation同时播放。
方法二:
Animationanim1=new AlphaAnimation(1.0f,0.5f);
mView.startAnimation(anim1);
anim1.setAnimationListener(newAnimationListener() {
@Override
publicvoid onAnimationStart(Animation animation) {
mView.startAnimation(anim2);//anim1,anim2一起放
}
@Override
publicvoid onAnimationRepeat(Animation animation) {
}
@Override
publicvoid onAnimationEnd(Animation animation) {
mView.startAnimation(anim3);//anim3在anim1放完后再放
如果anim2比anim1时间长,anim3会和anim2一起播放一段时间
}
});
方法三:
res/anim下的xml文件。用
有一些局限性,比如rotate的旋转角度必须给死,不能动态设置。
如果想实现alpha从1.0到0.0然后0.0到1.0.
Animationanim4=AnimationUtils.loadAnimation(Context context,R.anim.xxx);
android:duration="750"
android:fromAlpha="1.0"
android:toAlpha="0.0"
android:repeatMode="reverse"
android:repeatCount="2"
android:interpolator="@android:anim/linear_interpolator"
/>
不能够采取以下写法,实测会不显示,貌似alpha值会直接关联的,也就是第二个alpha动画虽然是让1s后开始播放,但是一开始就把view的alpha变成0。导致0~1s第一个alpha动画播放过程中alpha是0.当第一个alpha播放结束后,alpha一直是0,导致第二个alpha动画播放过程中alpha一直是0.
详细的没深究。所以牵扯到alpha动画时用这种写法要谨慎。
android:duration="1000"
android:fromAlpha="1.0"
android:toAlpha="0.0"
/>
android:startOffset=”1000”
android:duration="1000"
android:fromAlpha="0.0"
android:toAlpha="1.0"
/>
(3)view.clearAnimation后animation如果设置了监听,是否会执行onAnimationEnd方法?
答案是会。并且只有在动画执行过程中执行了view.clearAnimation才会执行的onAnimationEnd方法。
实测打log验证过。
看源码:
View的clearAnimation():
publicvoidclearAnimation() {
if(mCurrentAnimation!=null){
mCurrentAnimation.detach();
}
mCurrentAnimation=null;
invalidateParentIfNeeded();
}
Animation类的detach():
/**
*@hide
*/
publicvoiddetach() {
if(mStarted&& !mEnded){
mEnded=true;
guard.close();
fireAnimationEnd();
}
}
注意这个方法是hide的。
Animation类的fireAnimationEnd():
privatevoidfireAnimationEnd() {
if(mListener!=null){
if(mListenerHandler==null)mListener.onAnimationEnd(this);
elsemListenerHandler.postAtFrontOfQueue(mOnEnd);
}
}
发现clearAnimation()是会调用Animation监听的onAnimationEnd方法的。
(4)ObjectAnimator的坑
碰到一个bug,在不同系统上,一样的代码,结果objectAnimator动画时长不一样。
看源码:
publicfinal class ObjectAnimator extends ValueAnimator {
publicObjectAnimatorsetDuration(longduration) {
super.setDuration(duration);
returnthis;
}
}
ValueAnimator:
privatestatic float sDurationScale = 1.0f;
privatelong mDuration = (long)(300 * sDurationScale);
privatelong mUnscaledDuration = 300;
publicstatic void setDurationScale(float durationScale) {
sDurationScale= durationScale;
}
@Override
publicValueAnimatorsetDuration(long duration){
if(duration < 0) {
thrownew IllegalArgumentException("Animators cannot have negativeduration: " +
duration);
}
mUnscaledDuration= duration;
updateScaledDuration();
returnthis;
}
privatevoid updateScaledDuration() {
mDuration= (long)(mUnscaledDuration * sDurationScale);
}
publicvoid setStartDelay(long startDelay) {
this.mStartDelay= (long)(startDelay * sDurationScale);
mUnscaledStartDelay= startDelay;
}
实际上,在设置—开发者选项中有一项是动画程序时长缩放,
这一项应该是设置了sDurationScale.也就是这个系数。
有时候我们只是在程序中设置了setDuration,而没有设置setDurationScale.
你以为是1.0f的速度,结果开发者选项中改变了,导致动画快了或者慢了。这点要注意。
修改方法就是在程序中:
多加上setDurationScale。
(5)Activity设置进入,退出动画
TweenAnimation
Intentintent=newIntent(this,SecondActivity.class);
startActivity(intent);
overridePendingTransition(R.anim.enter_anim,R.anim.exit_anim);
publicvoidoverridePendingTransition(intenterAnim,intexitAnim) {}
对于一个Activity,它有进入动画和退出动画两个。
(6)音乐封面裁剪成圆形后,旋转动画的实现
旋转每次一周,并无限循环。currentValue到currentValue+360.正好360度。
旋转动画的逻辑有:
进入Activity判断音乐是否在放,在放的话开始动画。此时currentValue应该为0.
按下暂停键,动画停止(不恢复原位,停留在最后一帧)。
按下播放键,动画从上次暂停的地方开始继续播放。
使用ValueAnimator来实现。
publicvoid startAlbumRotateAnimator(){
try{
if(mService != null && mService.isPlaying()){
mAnimator= ObjectAnimator.ofFloat(mAlbum,
"Rotation",mCurrentRotateValue, mCurrentRotateValue+360);
mAnimator.setDuration(25000);
LinearInterpolatorlin = new LinearInterpolator();
mAnimator.setRepeatCount(ValueAnimator.INFINITE);
mAnimator.setInterpolator(lin);
mAnimator.addUpdateListener(newAnimatorUpdateListener() {
@Override
publicvoidonAnimationUpdate(ValueAnimatoranimation) {
mCurrentRotateValue= (Float) animation.getAnimatedValue();
}
});
mAnimator.start();
}
}
catch(RemoteException ex) {
}
}
代码里对这个Animator实现监听,可以监听这个旋转值的变化。
问题:如果是AnimatorSet,好几种动画组合,怎么分开监听各种动画的值?回头需要的时候研究下,应该也有现成的api.
mAnimator.end();//结束动画,返回原处
mAnimator.cancel();//结束动画,停留在最后一帧
mAniamtor.start();//动画开始