安卓进阶第五篇之常见动画的使用

Android中的动画有三种,分别是补间动画、帧动画、属性动画。

</p>

1. 补间动画

</p>
通过在两个关键帧之间补充渐变的动画效果来实现,其优点是可以节省空间。Android目前支持的补间动画有RotateAnimation(旋转)、ScaleAnimation(缩放)、AlphaAnimation(透明度)、TranslateAnimation(位移)、AnimationSet(组合)这5种。
实现补间动画的方式有两种:1.代码创建 2.使用xml

第一种:使用代码创建:
1.1 RotateAnimation(旋转动画)

/** 
* 创建旋转动画 
*/
private void createRotateAnimation() {
/**     
* 构造方法如下     
*fromDegrees、toDegrees表示开始、结束的角度(0度为水平方向右侧的开始角度),pivotXValue、pivotYValue代表旋转的中心位置,[0.0f-1.0f],     
*pivotXType、pivotYType表示旋转的类型(Animation.ABSOLUTE,、Animation.RELATIVE_TO_SELF、Animation.RELATIVE_TO_PARENT)     
*当type为Animation.ABSOLUTE时,这个个值为具体的像素值,当type为Animation.RELATIVE_TO_SELF或Animation.RELATIVE_TO_PARENT,这个个值为比例值,取值范围是[0f, 1.0f]     
*public RotateAnimation(float fromDegrees, float toDegrees, int pivotXType, float pivotXValue,int pivotYType, float pivotYValue) {     }    
*/    
//初始化RotateAnimation
RotateAnimation animation = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);    
//动画执行时间
animation.setDuration(2000);    
//动画重复次数-1表示不停重复    
//animation.setRepeatCount(-1);    
//给控件设置动画    
mTv.startAnimation(animation);
}

1.2 ScaleAnimation(缩放动画)

/** 
* 创建缩放动画 
*/
private void createScaleAnimation() {    
/**     
* 构造方法如下     
* fromX、toX 开始结束的X轴缩放比率[0.0f-1.0f],fromY、toYtoY开始结束的Y轴缩放比率[0.0f-1.0f],pivotXValue、pivotYValue代表旋转的中心位置,[0.0f-1.0f],     
* pivotXType、pivotYType表示旋转的类型(Animation.ABSOLUTE,、Animation.RELATIVE_TO_SELF、Animation.RELATIVE_TO_PARENT)     
* 当type为Animation.ABSOLUTE时,这个个值为具体的像素值,当type为Animation.RELATIVE_TO_SELF或Animation.RELATIVE_TO_PARENT,这个个值为比例值,取值范围是[0f, 1.0f]     
*  public ScaleAnimation(float fromX, float toX, float fromY, float toY,int pivotXType, float pivotXValue, int pivotYType, float pivotYValue) {}     
*/    
//初始化ScaleAnimation    
ScaleAnimation animation = new ScaleAnimation(1f, 0.5f, 1f, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);    
//动画执行时间    
animation.setDuration(2000);    
//动画重复次数-1表示不停重复    
//animation.setRepeatCount(-1);    
//给控件设置动画    
mTv.startAnimation(animation);
}

1.3 AlphaAnimation(透明度)

/** 
* 创建透明度渐变动画 
*/
private void createAlphaAnimation() {    
/***     
* 构造方法如下     
* fromAlpha、toAlpha表示透明度的起始值和结束值,0.0f表示全透明,1.0f表示不透明。     
* public AlphaAnimation(float fromAlpha, float toAlpha) {}     
*/    
//初始化AlphaAnimation    
AlphaAnimation animation = new AlphaAnimation(1.0f, 0.0f);    
//动画执行时间    animation.setDuration(2000);    
//动画重复次数-1表示不停重复    
//animation.setRepeatCount(-1);    
//给控件设置动画    
mTv.startAnimation(animation);
}

1.4 TranslateAnimation(位移)

 /**     
* 创建位移动画     
*/    
private void createTranslateAnimation() {        
/**         
* 构造方法如下         
* fromXType、toXType、fromYType、toYType(Animation.ABSOLUTE,、Animation.RELATIVE_TO_SELF、Animation.RELATIVE_TO_PARENT)         
* 当type为Animation.ABSOLUTE时,这个个值为具体的像素值,当type为Animation.RELATIVE_TO_SELF或Animation.RELATIVE_TO_PARENT,这个个值为比例值,取值范围是[0f, 1.0f]         
*public TranslateAnimation(int fromXType, float fromXValue, int toXType, float toXValue,int fromYType, float fromYValue, int toYType, float toYValue) {}              
*/        
TranslateAnimation animation = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0f,                
Animation.RELATIVE_TO_SELF, 0f, Animation.RELATIVE_TO_SELF, 0f, Animation.ABSOLUTE, 100);        
animation.setDuration(2000);        
//动画重复次数-1表示不停重复        
//animation.setRepeatCount(-1);
//动画结束后View停留在结束位置
//animation.setFillAfter(true);        
mTv.startAnimation(animation);    }

1.5 AnimationSet(组合)

/** * 创建组合动画 
*/
private void createAnimationSet(){    
AnimationSet animationSet = new AnimationSet(true);    
AlphaAnimation alphaAnimation = new AlphaAnimation(1.0f, 0.0f);    
ScaleAnimation scaleAnimation = new ScaleAnimation(1f, 0.5f, 1f, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);    
RotateAnimation rotateAnimation = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);    
TranslateAnimation translateAnimation = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0f, Animation.RELATIVE_TO_SELF, 0f, Animation.RELATIVE_TO_SELF, 0f, Animation.ABSOLUTE, 100);    animationSet.addAnimation(alphaAnimation);    
animationSet.addAnimation(scaleAnimation);    
animationSet.addAnimation(rotateAnimation);    
animationSet.addAnimation(translateAnimation);   
animationSet.setDuration(2000);    
animationSet.setRepeatCount(-1);    
mTv.startAnimation(animationSet);}

AnimationSet animationSet = new AnimationSet(true); true表示这个组合动画公用一个插值器,插值器的概念和使用方法,我会在文章的末尾进行说明。

第二种:使用xml创建,在res下创建anim文件夹,如图:

alpha_demo.xml:

<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"       
android:fromAlpha="1.0"       
android:toAlpha="0.0"       
android:duration="2000">
</alpha>
</rotate>

rotate_demo.xml:

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2000"        
android:fromDegrees="0"        
android:pivotX="50%"        
android:pivotY="50%"        
android:toDegrees="360">
</rotate>

scale_demo.xml:

<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"       
android:fromXScale="1.0"       
android:toXScale="0.5"       
android:fromYScale="1"       
android:toYScale="0.5"       
android:pivotX="50%"       
android:pivotY="50%"       
android:duration="2000">
</scale>

translate_demo.xml:

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"           
android:fromXDelta="0"           
android:toXDelta="0"           
android:fromYDelta="0"           
android:toYDelta="100"           
android:duration="2000">
</translate>

set_demo.xml:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"     
android:duration="2000"    >    
<scale        
android:fromXScale="1"        
android:fromYScale="1"        
android:pivotX="50%"        
android:pivotY="50%"        
android:toXScale="0.5"        
android:toYScale="0.5" />    
<rotate        
android:fromDegrees="0"        
android:pivotX="50%"        
android:pivotY="50%"        
android:toDegrees="360"/>    
<translate        
android:fromXDelta="0"        
android:fromYDelta="0"        
android:toXDelta="0"        
android:toYDelta="100"/>    
<alpha        
android:fromAlpha="1.0"        
android:toAlpha="0.1"/>
</set>

效果图:

补间动画效果图

2.帧动画

帧动画帧动画顾名思义,一帧一帧播放的动画就是帧动画。 帧动画和我们小时候看的动画片的原理是一样的,在相同区域快速切换图片给人们呈现一种视觉的假象感觉像是在播放动画,其实不过是多张图片在一帧一帧的切换罢了。切记,图片不易过多过大,不然容易产生OOM。

先在drawble下新建一个xml:

Paste_Image.png

frame_animation.xml:

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"                
android:oneshot="false">    
//oneshot属性表示是否循环播放,值为true则只播放一次。    
<item        android:drawable="@mipmap/animation1"        android:duration="200"/>   
<item        android:drawable="@mipmap/animation2"        android:duration="200"/>   
<item        android:drawable="@mipmap/animation3"        android:duration="200"/>    
<item        android:drawable="@mipmap/animation4"        android:duration="200"/>    
<item        android:drawable="@mipmap/animation5"        android:duration="200"/>   
<item        android:drawable="@mipmap/animation6"        android:duration="200"/>    
<item        android:drawable="@mipmap/animation7"        android:duration="200"/>    
<item        android:drawable="@mipmap/animation8"        android:duration="200"/>
</animation-list>

java代码:

/** 
* 帧动画 
*/
public class FrameAnimation extends AppCompatActivity {    
@Bind(R.id.img)    
ImageView mImg;    
@Bind(R.id.btn1)    
Button mBtn1;    
@Bind(R.id.btn2)    
Button mBtn2;    
AnimationDrawable animationDrawable;    
@Override    
protected void onCreate(Bundle savedInstanceState) {        
super.onCreate(savedInstanceState);        
setContentView(R.layout.activity_frame_animation);        
ButterKnife.bind(this);        
mImg.setImageResource(R.drawable.frame_animation);        
animationDrawable = (AnimationDrawable) mImg.getDrawable();    
}    
@OnClick({R.id.btn1, R.id.btn2})    
public void onClick(View view) {        
switch (view.getId()) {            
case R.id.btn1:                
animationDrawable.start();                
break;            
case R.id.btn2:                
animationDrawable.stop();                
break;        
}    
}}

效果如下:

帧动画效果图

3.属性动画

在Android3.0之后才引进的,属性动画改变的是对象的实际属性,如ImageView的缩放,ImageView的位置与大小属性值都改变了。属性动画不止可以应用于View,还可以应用于任何对象。属性动画只是表示一个值在一段时间内的改变,当值改变时要做什么事情完全是你自己决定的。ValueAnimator和ObjectAnimator是属性动画的两个核心类。

3.1 ValueAnimator:对一个范围内的值进行一个平滑的动画过渡效果
下面的动画是在2s内实现从100到50的一个动画,然后每次更新获取到值后进行你要的操作,我是这么做的:

private void createValueAnimator() {
//初始化ValueAnimator     
ValueAnimator valueAnimator = ValueAnimator.ofInt(100, 80);    
//监听动画   
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {        
@Override        
public void onAnimationUpdate(ValueAnimator animation) {            
int value = (int) animation.getAnimatedValue();//当前的值            
mImg.getLayoutParams().width = value;   
mImg1.getLayoutParams().height = value;         
mImg.requestLayout();        
}   
 });    
valueAnimator.setDuration(2000);//动画时长    
valueAnimator.start();//启动动画}

除了ValueAnimator.ofInt(),常用的还有ValueAnimator.ofFloat()、ValueAnimator.ofArgb(),ValueAnimator.ofFloat()是实现浮点数的平滑过渡,用法跟ValueAnimator.ofInt()差不多是一样的,那我们看看ValueAnimator.ofArgb(),实现颜色值的过渡,举个例子:

private void vreateValueAnimatorArgb(){    
//ValueAnimator.ofArgb()方法是在API Level 21中才加入的    
if(Build.VERSION.SDK_INT >= 21){        
ValueAnimator valueAnimator = ValueAnimator.ofArgb(R.color.red,R.color.blue);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {          
@Override            
public void onAnimationUpdate(ValueAnimator animation) {                
int color = (int) animation.getAnimatedValue();                
mImg.setBackgroundResource(color);                
mImg.requestLayout();                
Log.d("AAA",color+"");            
}        
});        
valueAnimator.setDuration(2000);//动画时长        
valueAnimator.start();//启动动画    
}}

3.2 ObjectAnimator 对任意对象的属性进行动画操作,那么,ObjectAnimator肯定是可以实现补间动画的效果咯,注意,要设置的对象的属性,必须要有set方法,不然不起作用的。
举一个例子,我们设置一个对象的缩放动画:

ObjectAnimator animator = ObjectAnimator.ofFloat(mImg, "scaleX", 1f, 2f);
animator.setDuration(2000);
animator.start();

这里我们设置对象的属性为scaleX,表示这个动画执行的时候,会在水平方向将mImg(mImg是个ImageView)的宽度拉伸两倍,由于mImg这个对象没有setScale()这个方法,所以这里就不能设置属性为"scale",这样是没有效果的。同样,我们也可以设备对象的旋转、透明度、平移的动画,只需要修改对象的属性就可以了,这里就不再举例。

3.3 跟补间动画类似,属性动画也可以将多个动画组合在一起执行,如果多个动画同时执行,则调用animatorSet.playTogether(),如果动画执行的先后顺序不一样,则通过animatorSet.play()获得一个AnimatorSet.Builder对象,这个对象有四个方法:
after(Animator anim) 将现有动画插入到传入的动画之后执行
after(long delay) 将现有动画延迟指定毫秒后执行
before(Animator anim) 将现有动画插入到传入的动画之前执行
with(Animator anim) 将现有动画和传入的动画同时执行

AnimatorSet animatorSet = new AnimatorSet();
ObjectAnimator alpha = ObjectAnimator.ofFloat(view, "alpha", 1f, 0f, 1f);
ObjectAnimator rotation = ObjectAnimator.ofFloat(view, "rotation", 0f, 360f);
ObjectAnimator translation = ObjectAnimator.ofFloat(view, "translationX", 400f, 0f);
ObjectAnimator scale = ObjectAnimator.ofFloat(view, "scaleX", 1f, 2f, 1f);
animatorSet.playTogether(alpha,rotation,translation,scale);//动画同时执行
//如果不同时执行,则如下,根据自己的需求可以自己调整
//animatorSet.play(alpha).with(translation).after(rotation).before(scale);
animatorSet.setDuration(5000);animatorSet.start();

3.4 跟补间动画一样,属性动画也可以使用xml的方式,在res下创建animator文件夹,如下:


可以使用的标签有<animator>、<objectAnimator> 和<set>,分别表示ValueAnimator、ObjectAnimator和AnimatorSet。比如上面我们用ObjectAnimator实现的旋转动画,用xml来写的话就是酱紫的:

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" 
android:duration="2000" 
android:propertyName="rotation" 
android:valueFrom="0" 
android:valueTo="360" 
android:valueType="floatType" />

<animator>和<set>标签就不举例啦,使用方法都是大同小异,大家多写几遍就会了,最后我们看一下在代码中如何使用这个xml:

Animator animator = AnimatorInflater.loadAnimator(context, R.animator.anim_test); //anim_test就是我们写的xml文件
animator.setTarget(view); //view表示我们要设置动画的对象
animator.start();

3.5属性动画也可以监听动画执行的状态,有两种方式,可以根据自己的需要选择,代码如下:
第一种:

animator.addListener(new Animator.AnimatorListener() { 
@Override 
public void onAnimationStart(Animator animation) { } 
@Override 
public void onAnimationEnd(Animator animation) { } 
@Override 
public void onAnimationCancel(Animator animation) { } 
@Override 
public void onAnimationRepeat(Animator animation) { } 
});

第二种

animator.addListener(new AnimatorListenerAdapter() { 
@Override 
public void onAnimationStart(Animator animation) { 
super.onAnimationStart(animation); 
} 
@Override 
public void onAnimationEnd(Animator animation) { 
super.onAnimationEnd(animation); 
} 
});

简单看一下效果(有点丑,哈哈!!!):

属性动画效果图

3.6 最后补充一下插值器的概念,所谓的插值器,就是我们执行的动画速度的改变规律,常用的插值器有以下几LinearInterpolator(匀速)、AccelerateInterpolator(加速)、AccelerateDecelerateInterpolator(先加速再减速)、BounceInterpolator(反弹数次后停止)、DecelerateInterpolator(减速),我们在代码或者xml中都可以使用插值器。
java代码中使用插值器:

RotateAnimation animation = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
animation.setDuration(2000);
animation.setInterpolator(new LinearInterpolator());//设置一个匀速的插值器
mTv.startAnimation(animation);

xml中使用插值器:

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"        
android:duration="2000"        
android:fromDegrees="0"        
android:pivotX="50%"        
android:pivotY="50%"        
android:interpolator="@android:anim/linear_interpolator"        
android:toDegrees="360">
</rotate>

最后看一下这5中插值器的效果,就拿上面的补间动画修改一下好了,效果如下:


加了插值器的效果图

动画的知识差不多就是这些了,如果觉得对你的开发有用,麻烦点下❤,谢谢支持。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,179评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,229评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,032评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,533评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,531评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,539评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,916评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,813评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,568评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,654评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,354评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,937评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,918评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,152评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,852评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,378评论 2 342

推荐阅读更多精彩内容