概述:
在Android動畫中悬钳,總共有兩種類型的動畫View Animation(視圖動畫)和Property Animator(屬性動畫)盐捷;
其中 :
a.View Animation包括Tween Animation(補間動畫)和Frame Animation(逐幀動畫);
b.Property Animator包括ValueAnimator和ObjectAnimation默勾;
首先碉渡,直觀上,他們有如下三點不同:
1母剥、引入時間不同:View Animation是API Level 1就引入的滞诺。Property Animation是API Level 11引入的,即Android 3.0才開始有Property Animation相關的API环疼。
2习霹、所在包名不同:View Animation在包android.view.animation中。而Property Animation API在包 android.animation中秦爆。
3序愚、動畫類的命名不同:View Animation中動畫類取名都叫XXXXAnimation,而在Property Animator中動畫類的取名則叫XXXXAnimator
大家都知道逐幀動畫主要是用來實現(xiàn)動畫的,而補間動畫才能實現(xiàn)控件的漸入漸出等限、移動爸吮、旋轉(zhuǎn)和縮放的;而Property Animator是在Android 3.0版本才引入的望门,之前是沒有的形娇。大家可能會覺得補間動畫和逐幀動畫已經(jīng)很全了,為什么還要引入Property Animator呢筹误?
1桐早、為什么引入Property Animator(屬性動畫)
我提出一個假設:請問大家,如何利用補間動畫來將一個控件的背景色在一分鐘內(nèi)從綠色變?yōu)榧t色厨剪?這個效果想必沒辦法僅僅通過改變控件的漸入漸出哄酝、移動、旋轉(zhuǎn)和縮放來實現(xiàn)吧祷膳,而這個效果是可以通過Property Animator完美實現(xiàn)的
這就是第一個原因:Property Animator能實現(xiàn)補間動畫無法實現(xiàn)的功能
大家都知道陶衅,補間動畫和逐幀動畫統(tǒng)稱為View Animation,也就是說這兩個動畫只能對派生自View的控件實例起作用直晨;而Property Animator則不同搀军,從名字中可以看出屬性動畫,應該是作用于控件屬性的勇皇!正因為屬性動畫能夠只針對控件的某一個屬性來做動畫罩句,所以也就造就了他能單獨改變控件的某一個屬性的值!比如顏色敛摘!這就是Property Animator能實現(xiàn)補間動畫無法實現(xiàn)的功能的最重要原因门烂。
我們得到了第二點不同:View Animation僅能對指定的控件做動畫,而Property Animator是通過改變控件某一屬性值來做動畫的着撩。
假設我們將一個按鈕從左上角利用補間動畫將其移動到右下角诅福,在移動過程中和移動后匾委,這個按鈕都是不會響應點擊事件的。這是為什么呢氓润?因為補間動畫僅僅轉(zhuǎn)變的是控件的顯示位置而已赂乐,并沒有改變控件本身的值。View Animation的動畫實現(xiàn)是通過其Parent View實現(xiàn)的咖气,在View被drawn時Parents View改變它的繪制參數(shù)挨措,這樣雖然View的大小或旋轉(zhuǎn)角度等改變了,但View的實際屬性沒變崩溪,所以有效區(qū)域還是應用動畫之前的區(qū)域浅役;我們看到的效果僅僅是系統(tǒng)作用在按鈕上的顯示效果,利用動畫把按鈕從原來的位置移到了右下角伶唯,但按鈕內(nèi)部的任何值是沒有變化的觉既,所以按鈕所捕捉的點擊區(qū)域仍是原來的點擊區(qū)域。(下面會舉例來說明這個問題)
這就得到了第三點不同:補間動畫雖能對控件做動畫乳幸,但并沒有改變控件內(nèi)部的屬性值瞪讼。而Property Animator則是恰恰相反,Property Animator是通過改變控件內(nèi)部的屬性值來達到動畫效果的
2粹断、舉例說明補間動畫的點擊區(qū)域問題
下面我們就利用TranslateAnimation來做一個移動動畫的例子符欠,看它的點擊區(qū)域是否會變搁进。
我們先來看看效果
在效果圖中坠非,首先,我給textview添加了點擊響應忧吟,當點擊textview時养筒,會彈出Toast曾撤。
然后,當我點擊按鈕的時候晕粪,textview開始向右下角移動盾戴。
從結(jié)果中可以看出,在移動前兵多,點擊textview是可以彈出toast的的,在移動后橄仆,點擊textview時則沒有響應剩膘,相反,點擊textview的原來所在區(qū)域則會彈出toast.
這就論證了不同第三點:補間動畫雖能對控件做動畫盆顾,但并沒有改變控件內(nèi)部的屬性值
Android中常用的動畫都在這里了怠褐,包含了基本的動畫【透明度動畫,縮放動畫您宪,旋轉(zhuǎn)動畫奈懒,位移動畫】奠涌;還有就是這四種動畫的組合實現(xiàn); 還有布局動畫磷杏,就是在加載布局時的動畫溜畅;還有Activity跳轉(zhuǎn)的動畫。 效果圖如下:
1. Android基礎動畫
如果是xml的方式寫要在res下創(chuàng)建anim文件夾內(nèi)寫
透明度動畫
xml:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha
android:duration="1000"
android:fromAlpha="0.0"
android:toAlpha="1.0"
/>
</set>
代碼:
AlphaAnimation animation = new AlphaAnimation(0, 1);
animation.setDuration(3000);
animation.setFillAfter(true);
mImg.setAnimation(animation);
縮放動畫
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale
android:duration="1000"
android:fromXScale="0"
android:fromYScale="0"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1"
android:toYScale="1" />
</set>
代碼:
/**
* 第一個參數(shù)fromX為動畫起始時 X坐標上的伸縮尺寸
* 第二個參數(shù)toX為動畫結(jié)束時 X坐標上的伸縮尺寸
* 第三個參數(shù)fromY為動畫起始時Y坐標上的伸縮尺寸
* 第四個參數(shù)toY為動畫結(jié)束時Y坐標上的伸縮尺寸
* 說明: 0.0表示收縮到?jīng)]有;1.0表示正常無伸縮;值小于1.0表示收縮;值大于1.
* 第五個參數(shù)pivotXType為動畫在X軸相對于物件位置類型
* 第六個參數(shù)pivotXValue為動畫相對于物件的X坐標的開始位置
* 第七個參數(shù)pivotXType為動畫在Y軸相對于物件位置類型
* 第八個參數(shù)pivotYValue為動畫相對于物件的Y坐標的開始位置
*/
private void playAnimator(View view) {
ObjectAnimator objectAnimatorX = ObjectAnimator.ofFloat(view, "scaleX", 1.0f, 1.3f, 0.9f, 1.15f, 0.95f, 1.02f, 1.0f);
ObjectAnimator objectAnimatorY = ObjectAnimator.ofFloat(view, "scaleY", 1.0f, 1.3f, 0.9f, 1.15f, 0.95f, 1.02f, 1.0f);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(objectAnimatorX).with(objectAnimatorY);
animatorSet.setDuration(1000);
animatorSet.start();
}
Animation animation = new ScaleAnimation(0, 1
animation.setDuration(1000);
iv.startAnimation(animation);
旋轉(zhuǎn)動畫
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<rotate
android:duration="1000"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="360" />
</set>
代碼:
/**
* 第一個參數(shù)fromDegrees為動畫起始時角度
* 第二個參數(shù)toDegrees為動畫結(jié)束角度
* 第三個參數(shù)pivotXType為動畫在X軸相對于物件位置類型
* 第四個參數(shù)pivotXValue為動畫相對于物件的X坐標的開始位置
* 第五個參數(shù)pivotXType為動畫在Y軸相對于物件位置類型
* 第六個參數(shù)pivotYValue為動畫相對于物件的Y坐標的開始位置
*/
Animation animation = new RotateAnima
animation.setDuration(1000);
iv.startAnimation(animation);
位移動畫
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="2000"
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="500"
android:interpolator="@android:anim/accelerate_interpolator"
android:toYDelta="0" />
</set>
代碼:
/**
* 第一個參數(shù)fromDegrees為動畫起始時角度
* 第二個參數(shù)toDegrees為動畫結(jié)束角度
* 第三個參數(shù)pivotXType為動畫在X軸相對于物件位置類型
* 第四個參數(shù)pivotXValue為動畫相對于物件的X坐標的開始位置
* 第五個參數(shù)pivotXType為動畫在Y軸相對于物件位置類型
* 第六個參數(shù)pivotYValue為動畫相對于物件的Y坐標的開始位置
*/
Animation animation = new RotateAnima
animation.setDuration(1000);
iv.startAnimation(animation);
/**
* 第一個參數(shù)fromXDelta為動畫起始時的x坐標
* 第二個參數(shù)toXDelta為動畫結(jié)束時的x坐標
* 第三個參數(shù)fromYDelta為動畫起始時的y坐標
* 第四個參數(shù)toYDelta為動畫結(jié)束時的y坐標
*/
Animation animation = new Translat
animation.setDuration(2000);
/**設置插值器:先加速极祸,后減速**/
animation.setInterpolator(new Acce
iv.startAnimation(animation);
2.組合動畫
先播放縮放動畫慈格,完成后播放旋轉(zhuǎn)動畫
Animation animation = AnimationUtils.loadAnimation(this, R.anim.scale);
iv.startAnimation(animation);
final Animation animation2 = AnimationUtils.loadAnimation(this, R.anim.rotate);
animation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
iv.startAnimation(animation2);
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
先播放旋轉(zhuǎn)動畫,完成后播放位移動畫遥金,在xml中設置第二個動畫執(zhí)行的等待時間
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<rotate
android:duration="1000"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="360" />
<translate
android:duration="1000"
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="500"
android:startOffset="1000"
android:interpolator="@android:anim/accelerate_interpolator"
android:toYDelta="0" />
</set>
重復的透明度動畫-閃爍
AlphaAnimation alphaAnimation = new AlphaAnimation(0.1f, 1.0f);
alphaAnimation.setDuration(1000);
alphaAnimation.setRepeatCount(10);
/**倒序重復REVERSE 正序重復RESTART**/
alphaAnimation.setRepeatMode(Animation.REVERSE);
iv.startAnimation(alphaAnimation);
重復的位移動畫-抖動
Animation translateAnimation = new TranslateAnimation(-10, 10, 0, 0);
translateAnimation.setDuration(100);
translateAnimation.setRepeatCount(10);
/**倒序重復REVERSE 正序重復RESTART**/
translateAnimation.setRepeatMode(Animation.REVERSE);
iv.startAnimation(translateAnimation);
3.幀動畫
在drawable文件夾下建立文件
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
>
<item android:drawable="@mipmap/windmill_1"
android:duration="500">
</item>
<item android:drawable="@mipmap/windmill_2"
android:duration="500">
</item>
<item android:drawable="@mipmap/windmill_3"
android:duration="500">
</item>
<item android:drawable="@mipmap/windmill_4"
android:duration="500">
</item>
<item android:drawable="@mipmap/windmill_5"
android:duration="500">
</item>
<item android:drawable="@mipmap/windmill_6"
android:duration="500">
</item>
<item android:drawable="@mipmap/windmill_7"
android:duration="500">
</item>
</animation-list>
在activity中調(diào)用
iv.setImageResource(R.drawable.ring_animation);
AnimationDrawable animationDrawable = (AnimationDrawable) iv.getDrawable();
animationDrawable.start();
4.布局動畫 這是一個ListView的加載布局動畫
先建立動畫文件,從透明到不透明并且大小從0到原大小
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/decelerate_interpolator" >
<scale
android:duration="1000"
android:fromXScale="0.1"
android:fromYScale="0.1"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1.0"
android:toYScale="1.0" />
<alpha
android:duration="1000"
android:fromAlpha="0"
android:toAlpha="1.0" />
</set>
在activity中的用法
ListView listView = (ListView) findViewById(R.id.listview);
List<String> datas = new ArrayList<>();
for (int i = 0; i < 18; i++) {
datas.add("萬能適配器測試" + i);
}
LayoutAnimationController layoutAnimationController= new LayoutAnimationController(AnimationUtils.loadAnimation(this, R.anim.zoom_in));
layoutAnimationController.setOrder(LayoutAnimationController.ORDER_NORMAL);
listView.setLayoutAnimation(layoutAnimationController);
listView.setAdapter(new CommonAdapter<String>(this, datas, R.layout.item) {
@Override
protected void convertView(View item, String s) {
TextView textView = CommonViewHolder.get(item, R.id.textView);
textView.setText(s);
}
});
5.Activity跳轉(zhuǎn)動畫
退出動畫:從不透明到透明并且大小從原大小到0
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/decelerate_interpolator"
android:zAdjustment="top" >
<scale
android:duration="@android:integer/config_mediumAnimTime"
android:fromXScale="1.0"
android:fromYScale="1.0"
android:pivotX="50%p"
android:pivotY="50%p"
android:toXScale="0.1"
android:toYScale="0.1" />
<alpha
android:duration="@android:integer/config_mediumAnimTime"
android:fromAlpha="1.0"
android:toAlpha="0" />
</set>
進入動畫:從透明到不透明并且大小從0到原大小
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/decelerate_interpolator" >
<scale
android:duration="1000"
android:fromXScale="0.1"
android:fromYScale="0.1"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1.0"
android:toYScale="1.0" />
<alpha
android:duration="1000"
android:fromAlpha="0"
android:toAlpha="1.0" />
</set>
在Activity中的用法
startActivity(new Intent(this,SecondActivity.class));
overridePendingTransition(R.anim.zoom_in,R.anim.zoom_out);