Animation,Animator学习

(1)Animation动画类学习总结

AlphaAnimation,TranslateAnimation,ScaleAnimation,RotateAnimation.

<alpha/>,<translate/>,<scale/>,<rotate/>

透明度,位移,缩放,旋转

AlphaAnimation设定开始和结束的alpha值,float类型,0.0f1.0f

TranslateAnimation,设定4个,开始与结束的xy坐标。注意,这里不是绝对坐标,而是距离当前组件所在位置的相对距离,给正数说明在组件右边,给负数说明在组件左边。

ScaleAnimation,设定开始和放大后的xy倍数,浮点数,1.0f为原来组件大小。要设定一个点,动画相对于物件的X坐标的开始位置,和动画相对于物件的y坐标的开始位置(这个要多看下效果,不好描述,会决定动画缩放的效果和最后一帧的位置)

RotateAnimation,设定旋转的开始角度与结束角度。正数是顺时针转,负数是逆时针转.360为一周。还要设定组件围绕哪个点旋转。给出那个点的xy坐标。

javacode里面引用res/anim下的xxx.xml文件:

AnimationmAnimation=AnimationUtils.loadAnimation(this,R.anim.xxx);//注意是AnimationUtils下的静态方法,utilutility的缩写,工具的意思

javacode里面用mAnimation.setDuration(3000)来设置动画持续的事件。

如果是res/drawable下的xml文件的话用。android:duration="150"

javacode里面用mAnimation.setFillAfter(true)让动画停止在最后一帧。

xml要在<setandroid:fillAfter="true"><set/>注意放在<alpha/>,<translate/>,<scale/>,<rotate/>中是无效的。

系统默认是设置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

<animation-list

android:oneshot="false"> <!-- android:oneshotfalse,说明帧动画只播放一次,并停留在最后一帧;默认为true,动画无限循环播放-->

<itemandroid:drawable="@drawable/a1"android:duration="150"></item>

<itemandorid:drawable="@drawable/a2"android:duration="150"></item>

<itemandorid:drawable="@drawable/a3"android:duration="150"></item>

<itemandorid:drawable="@drawable/a4"android:duration="150"></item>

<itemandorid:drawable="@drawable/a5"android:duration="150"></item>

<itemandorid:drawable="@drawable/a6"android:duration="150"></item>

</animation-list>

布局文件中的引用

<ImageView

android:layoutHeight="wrap_content"

android:layoutWidth="wrap_content"

android:src="@drawale/animation" <!--这里的资源设置需要留意,它引用的是我们开始建立的xml文件,而不是一张图片-->

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);//anim3anim1放完后再放

如果anim2anim1时间长,anim3会和anim2一起播放一段时间

}

});

方法三:

res/anim下的xml文件。用<set></set>标签

有一些局限性,比如rotate的旋转角度必须给死,不能动态设置。

如果想实现alpha1.00.0然后0.01.0.

Animationanim4=AnimationUtils.loadAnimation(Context context,R.anim.xxx);

<alpha

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后开始播放,但是一开始就把viewalpha变成0。导致0~1s第一个alpha动画播放过程中alpha0.当第一个alpha播放结束后,alpha一直是0,导致第二个alpha动画播放过程中alpha一直是0.

详细的没深究。所以牵扯到alpha动画时用这种写法要谨慎。

<alpha

android:duration="1000"

android:fromAlpha="1.0"

android:toAlpha="0.0"

/>

<alpha

android:startOffset=”1000”

android:duration="1000"

android:fromAlpha="0.0"

android:toAlpha="1.0"

/>

(3)view.clearAnimationanimation如果设置了监听,是否会执行onAnimationEnd方法?

答案是会。并且只有在动画执行过程中执行了view.clearAnimation才会执行的onAnimationEnd方法。

实测打log验证过。

看源码:

ViewclearAnimation():

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)音乐封面裁剪成圆形后,旋转动画的实现

旋转每次一周,并无限循环。currentValuecurrentValue+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();//动画开始


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值