01 屬性動畫背景
屬性動畫出現(xiàn)之前,有幀動畫和View動畫
- 幀動畫(FrameAnimation)就是將一個(gè)動畫分成多個(gè)幀。有點(diǎn)類似膠卷電影。
- View動畫最大的缺點(diǎn)就是不具有交互性。監(jiān)聽器和View動畫脫離。優(yōu)點(diǎn)是效率高。
為了實(shí)現(xiàn)更豐富的動畫效果,Google推出了屬性動畫。
02 屬性動畫涉及的類
| 類 | 描述 |
|---|---|
| ObjectAnimator | 屬性動畫最重要的類了 |
ObjectAnimator.ofFloat(動畫View,"屬性",值) |
|
| ValueAnimator | 這個(gè)有點(diǎn)類似于幀動畫 |
| Animator.AnimatorListener | 監(jiān)聽動畫開始,結(jié)束,取消,重復(fù)
|
| AnimatorListenerAdapter | 選擇性監(jiān)聽 |
2.1Class ObjectAnimator
比如要實(shí)現(xiàn)View的X軸方向平移200px
ObjectAnimator ani = ObjectAnimator.ofFloat(view,"translationX",200);
ani.setDuration(300); // 設(shè)置動畫持續(xù)時(shí)間
ani.start();
注意:屬性動畫通過反射實(shí)現(xiàn)的。說白的比如你的動畫要調(diào)整View的高度,那么你的View要有getHeight()方法。如果沒有的話可以使用包裝類。
2.2 Class ValueAnimator
舉個(gè)栗子:實(shí)現(xiàn)類似于LED燈的橫幅效果

加載慢LED.gif
// Fragment 類中代碼
public void initView(View view) {
final ImageView v = view.findViewById(R.id.view_movable);
// 設(shè)置水平滑動的范圍
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, getResources().getDisplayMetrics().widthPixels - v.getLayoutParams().width);
valueAnimator.setTarget(v);
valueAnimator.setRepeatCount(-1); //重復(fù)次數(shù) ,-1 表示無限循環(huán)
valueAnimator.setRepeatMode(ValueAnimator.REVERSE);
valueAnimator.setDuration(2000); // 一次動畫的時(shí)間長度
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float f = (float) animation.getAnimatedValue();
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) v.getLayoutParams();
params.leftMargin = (int) f;
v.setLayoutParams(params);
System.err.print(f);
}
});
valueAnimator.start(); // 開始動畫
}
2.3 AnimatorListener 動畫監(jiān)聽
valueAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
Log.d("fragment","動畫片要要開始了");
}
@Override
public void onAnimationEnd(Animator animation) {
Log.d("fragment","動畫GG");
}
@Override
public void onAnimationCancel(Animator animation) {
Log.d("fragment","動畫被取消了,讓我們做一些有趣的事情吧");
}
@Override
public void onAnimationRepeat(Animator animation) {
Log.d("fragment","再看一片動畫");
}
});
// 要覆蓋的方法太多 怎么辦呢? 看下面
valueAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
}
});
2.4 Class AnimatorSet 組合動畫
四個(gè)方法
-
after(Animator anim)看下面代碼 -
after(long delay)將現(xiàn)有的動畫延遲執(zhí)行 -
before(Animator anim)看下面代碼 -
with(Animator anim)看下面代碼
// 我感覺幾個(gè)api解釋起來比較拗口,直接看下面的play函數(shù)
Animator animator1 = ObjectAnimator.ofFloat(v,"translationX",0.0f,200f,0f);
Animator animator2 = ObjectAnimator.ofFloat(v,"scaleX",1.0f,2.0f);
Animator animator3 = ObjectAnimator.ofFloat(v,"rotationX",0.0f,90.0f,0.0f);
AnimatorSet set = new AnimatorSet();
set.setDuration(1000);
set.play(animator1).with(animator2).after(animator3);
// 從英語的角度,很容易讀懂上面這一行代碼,先3再1,2同時(shí)
set.start();
Class PropertyValuesHolder 組合動畫和Class AnimatorSet區(qū)別在于動畫的執(zhí)行沒有先后順序
3 在XML中使用屬性動畫
動畫設(shè)計(jì)到的屬性都太多了,把它定義在xml可以減少代碼數(shù)量,而且可以復(fù)用。
- 在res文件夾下建立animator文件夾,cd進(jìn)去創(chuàng)建anim.xml 文件
- 下面是一個(gè)動畫的例子
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:duration="3000"
android:propertyName="scaleX"
android:valueFrom="1"
android:valueTo="2"
android:valueType="floatType">
</objectAnimator>
</set>
- 代碼中調(diào)用
Animator animator = AnimatorInflater.loadAnimator(this ,R.animator.anim);
animator.setTarget(v);
animator.start();